﻿using FormatUtil;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Data;
using RedisHelp;
using StackExchange.Redis;

using Newtonsoft.Json;

using DataModel;
using System.Globalization;
using HPSocket;
using System.Xml.Linq;


namespace SanitationTcpGw
{
    class Program
    {

        public enum AppState
        {
            Starting, Started, Stoping, Stoped, Error
        }

        static private AppState appState = AppState.Stoped;
        static HPSocket.Tcp.TcpServer server = new HPSocket.Tcp.TcpServer();



        //已处理的数据包数量
        private static UInt64 ProcessedCount = 0;
        private static readonly object ProcessedCountObj = new object();
        private static readonly ushort TcpPort = ushort.Parse(ConfigurationManager.AppSettings["TcpPort"]);
        private static readonly string HisDataBaseName = ConfigurationManager.AppSettings["HisDataBaseName"];
        private static readonly int UpdatePositionInterval = int.Parse(ConfigurationManager.AppSettings["UpdatePositionInterval"]);
        private static readonly string ImageSavePath = ConfigurationManager.AppSettings["ImageSavePath"];
        private static readonly string AuthenticationCode = ConfigurationManager.AppSettings["AuthenticationCode"].ToString();
        private static readonly string RedisHosts = ConfigurationManager.AppSettings["RedisHosts"];
        private static Timer StatusTimer = null;
        public static Dictionary<string, IntPtr> _PhoneSocketMap = new Dictionary<string, IntPtr>();
        //private static ServiceHost DownLinkServiceHost = new ServiceHost(typeof(SendMsgServer));


        private static readonly int MessageheadLength = 15;
        private static Hashtable HashMsgID = new Hashtable();

        private static Queue<SourceData> _recvPakageTcpQue = new Queue<SourceData>();
        static object _lockRecvQue = new object();

        private static Queue<SourceData> _sendPakageTcpQue = new Queue<SourceData>();
        static object _lockSendQue = new object();
        private static List<Queue<Gps>> _insertSqlList = new List<Queue<Gps>>();
        static object _lockSqlQue = new object();

        private static List<Queue<HandleData808>> _handleDataList = new List<Queue<HandleData808>>();
        private static List<object> _lockHandleList = new List<object>();

        //用于缓存已解析过的GPS数据
        public static Dictionary<string, Gps> GPSTable = new Dictionary<string, Gps>();
        //专门用于更新当前车辆状态SQL缓存
        public static List<string> UpdateSqlList = new List<string>();

        static Dictionary<string, ImageData> MultiMediaDic = new Dictionary<string, ImageData>();

        private static Timer TimeOutTimePhoto = null;
        //private static Timer TimeTer_ThisHistory = null;


        public static RedisHelper redis = new RedisHelper(0);
        public static RedisHelper redisGps = new RedisHelper(8, RedisHosts);
        private static Queue<GpsInfo> _redisGpsCacheQ = new Queue<GpsInfo>();
        private static long sdDataCount = 0;
        private static object sdObj = new object();
        private static List<string> _errorSql = new List<string>();

        //多媒体数据列表
        private static Hashtable MultiMediaList = new Hashtable();

        private static Dictionary<string, Dictionary<int, HandleData808>> rec0104SubMsgDic = new Dictionary<string, Dictionary<int, HandleData808>>();
        public static Dictionary<string, string> downSendMsgDic = new Dictionary<string, string>();

        private static Dictionary<string, DeviceInfo> _DeviceInfoAll = new Dictionary<string, DeviceInfo>();
        private static Dictionary<IntPtr, DeviceInfo> _DevOnlineRecordInfo = new Dictionary<IntPtr, DeviceInfo>();
        private static DateTime _nowDt = DateTime.Now;
        static IntPtr _conn = IntPtr.Zero;
        public static Dictionary<int, string> _RealTimeGps = new Dictionary<int, string>();

        public static FixedTimeTask fixedTimeTask = new FixedTimeTask(1, 0);

       static private List<Gps> updateLocation(string sql1)
        {
          
            DataTable devDT2 = DBHelp.DBHelp.QueryDataFromDB(sql1);
            List<Gps> ltall = new List<Gps>();
            if (devDT2 != null && devDT2.Rows.Count > 0)
            {
              
                for (int i = 0; i < devDT2.Rows.Count; i++)
                {
                    string lat = devDT2.Rows[i]["lat"] == DBNull.Value ? "" : devDT2.Rows[i]["lat"].ToString();
                    string lng = devDT2.Rows[i]["lng"] == DBNull.Value ? "" : devDT2.Rows[i]["lng"].ToString();
                    string direction = devDT2.Rows[i]["direction"] == DBNull.Value ? "" : devDT2.Rows[i]["direction"].ToString();
                    string mileage = devDT2.Rows[i]["mileage"] == DBNull.Value ? "" : devDT2.Rows[i]["mileage"].ToString();
                    string carL = devDT2.Rows[i]["car_location"] == DBNull.Value ? "" : devDT2.Rows[i]["car_location"].ToString();
                    string dt = devDT2.Rows[i]["data_time"] == DBNull.Value ? "" : devDT2.Rows[i]["data_time"].ToString();
                    Gps gps = new Gps();
                    gps.PosY = double.Parse(lat);
                    gps.PosX = double.Parse(lng);
                    gps.alarm = 0;
                    gps.alarmDetail = "";
                    gps.high = 0;
                    gps.Speed = 0;
                    gps.GpsTime = DateTime.Parse(dt);
                    gps.Direction = int.Parse(direction);
                    AttachData attachData = new AttachData();
                    attachData.Mileage = int.Parse(mileage);
                    attachData.OilMass = 0;
                    gps.statusDetail = "";
                    gps.RegionInfo = "";
                    gps.PlaceInfo = carL;
                    gps.Attach = attachData;
                    ltall.Add(gps);
                }
            }

            return ltall;

 
        
        }
       //static private List<DeviceInfo> selectdev()
       // {
       //     string sql1 = "SELECT * from base_device where imei in('3705040467','41905768969','866888020534690','866888020538022','868888020525177','86688802052906','866888020523594','41905765533','866888020537982','866888020531068','866888020548229','866888020537537','866888020533155','866888020533056','866888020545993','866888020526878','866888020545191','866888020532728','866888020526993','3705041457','56704838084','866888020535143','41905768899','866888020535424')";
       //     //string sql1 = "SELECT * from base_device where imei in('866888020545217')";
       //     DataTable devDT2 = DBHelp.DBHelp.QueryDataFromDB(sql1);
       //     List<DeviceInfo> ltall = new List<DeviceInfo>();

       //     if (devDT2 != null && devDT2.Rows.Count > 0)
       //     {

       //         for (int i = 0; i < devDT2.Rows.Count; i++)
       //         {
       //             string device_id = devDT2.Rows[i]["device_id"] == DBNull.Value ? "" : devDT2.Rows[i]["device_id"].ToString();
       //             string device_phone_num = devDT2.Rows[i]["device_phone_num"] == DBNull.Value ? "" : devDT2.Rows[i]["device_phone_num"].ToString();

       //             DeviceInfo deviceInfo = new DeviceInfo();
       //             deviceInfo.deviceId = int.Parse(device_id);
       //             deviceInfo.deviceNo = device_phone_num;
               
       //             ltall.Add(deviceInfo);
       //         }
       //     }
       //     return ltall;

       // }
        public static string ltGpsToSqlNew(List<Gps> ltall)
        {
            StringBuilder stringBuilder = new StringBuilder();

            lock (sdObj)
            {
                sdDataCount += ltall.Count();
            }
            stringBuilder.Append("INSERT INTO");
            foreach (Gps gps in ltall)
            {
                stringBuilder.Append(" d"+gps.PhoneNum + $" USING dev_gps_history TAGS ( {gps.deviceId},'{gps.PhoneNum}') VALUES ( ");
                stringBuilder.Append($"{GwUtil.DateTimeToUtcM(gps.GpsTime)},now,{gps.PosY},{gps.PosX},{gps.alarm},'{gps.alarmDetail}',{gps.high}," +
                    $"{gps.Speed},{gps.Direction},{gps.Attach.Mileage},{(int)gps.Attach.OilMass},0,'{gps.statusDetail}','{gps.RegionInfo + gps.PlaceInfo}') ");
            }
            return stringBuilder.ToString()+";";
        }
        static void Main(string[] args)
        {
            System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
            try
            {
                Console.OutputEncoding = Encoding.UTF8;
                System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
                LogHelp.IniteLog();
                DBHelp.DBHelp.Init();
                _conn = TDUtilsTools.TDConnection("36.134.79.195", "root", "Hbbd8991@", "bdmc_sanitation", 0);
 
               // string sql12 = "SELECT * FROM `dev_gps_history` where device_id=278 and data_time>'2022-07-16' and data_time<'2022-07-17' order by data_time";
               // var gps1 =   updateLocation(sql12);

               // sql12 = "SELECT * FROM `dev_gps_history` where device_id=278 and data_time>'2022-07-15' and data_time<'2022-07-16'  order by data_time";
               // var gps2 = updateLocation(sql12);
 
               //var devs =  selectdev();

               // foreach (var dev1 in devs)
               // {
               //     //string dele = "DELETE FROM  d"+dev1.deviceNo + " where data_time > '"+GwUtil.DateTimeToUtcM(DateTime.Parse("2023-01-01")) + "' and data_time < '"+GwUtil.DateTimeToUtcM(DateTime.Parse("2023-02-01"))+"';";

               //     string dele = "DELETE FROM  d" + dev1.deviceNo + " where data_time > '2023-01-01 00:00:00.100' and data_time < '2023-02-01 00:00:00.100';";
               //     TDUtilsTools.ExecuteUpdate(_conn, dele);
               //     Console.WriteLine(dele);
               // }


               // int days = 0;
               // for (DateTime startTime = DateTime.Parse("2023-01-04"); startTime < DateTime.Parse("2023-03-01"); startTime =startTime.AddDays(1))
               // {
               //     List<Gps> gps = new List<Gps>();
               //     if (days%2==0)
               //     {
               //         gps = gps1;
               //     }
               //     else
               //     {
               //         gps = gps2;
               //     }
               //     List<Gps> allgps = new List<Gps>();

               //     foreach (var item in devs)
               //     {
               //         foreach (var g in gps)
               //         {
               //             g.deviceId = item.deviceId.ToString();
               //             g.PhoneNum = item.deviceNo;
               //             DateTime dt = startTime.AddHours(g.GpsTime.Hour).AddMinutes(g.GpsTime.Minute).AddSeconds(g.GpsTime.Second);
               //             g.GpsTime = dt;
               //             allgps.Add(g);
               //         }
               //         string sqlss = ltGpsToSqlNew(allgps);
               //         TDUtilsTools.ExecuteQuery(_conn, sqlss);
               //         allgps.Clear();
               //         Console.WriteLine(startTime+item.deviceNo);
               //     }
                
               //     days++;
               // }

               // Console.WriteLine("完成");
               // Console.ReadLine();
                //string sql = "update dev_online_record set end_time = now(), online_state = 2 where online_state =1;update dev_gps_realtime set online_status=2;";
                //DBHelp.DBHelp.ExecSql(sql);

                string sql1 = "select device_id,device_phone_num from dev_gps_realtime;";
                DataTable devDT2 = DBHelp.DBHelp.QueryDataFromDB(sql1);

                if (devDT2 != null && devDT2.Rows.Count > 0)
                {
                    lock (_RealTimeGps)
                    {
                        _RealTimeGps.Clear();
                    }
                    for (int i = 0; i < devDT2.Rows.Count; i++)
                    {
                        int deviceId = devDT2.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT2.Rows[i]["device_id"].ToString());
                        string device_phone_num = devDT2.Rows[i]["device_phone_num"] == DBNull.Value ? "" : devDT2.Rows[i]["device_phone_num"].ToString();
                        lock (_RealTimeGps)
                        {
                            _RealTimeGps[deviceId] = device_phone_num;
                        }

                    }
                }
                SelectDeviceInfo();

                UpdateRedisData();
                SelectCurDayTaskPlan("person");
                SelectCurDayTaskPlan("car");
                TransDataWorkerHY.Start();



                InitMsgId();
                InitGpsList();
                InitHandleDataList();
                InitAndStartThreads();
                InitTcpServer();
                StatusTimer = new Timer(ShowStatus, null, 10000, 60000);
                TimeOutTimePhoto = new Timer(CheckOutTimePhoto, null, 10 * 60000, 10 * 60000);

                fixedTimeTask.DoWork += FixedTimeTaskDoWork;
                //FixedTimeTaskDoWork(-27);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Main", ex.ToString());
                LogHelp.WriteeLog("Main", ex.ToString());
            }

            //Console.ReadLine();
        }
        private static void FixedTimeTaskDoWork()
        {
            FixedTimeTaskDoWork(0);

        }
        private static void FixedTimeTaskDoWork(double days)
        {
            string date = DateTime.Now.AddDays(days).ToString("yyyy-MM-dd");
            LogHelp.WriteeLog("", date + "FixedTimeTask_DoWork");
            try
            {
                CalcReportCheckPointPerson(date);
            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("", ex.ToString());
            }
            try
            {
                CalcReportCheckPointCar(date);
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("", ex.ToString());
            }

        }

        private static void CalcReportCheckPointCar(string date)
        {

            string sqlStr = "SELECT tcw.plan_detail_id,tcw.work_plan_type,tcw.work_plan_id,tcw.work_team_id, tcw.person_id,per.person_name,tcw.effect_date,tcw.device_id ,car.car_id,car.car_num" +
                 ", tcw.start_span,tcw.end_span,fen.check_names,fen.check_points,fen.fence_id" +
                 " FROM  report_check_work as tcw,base_person as per,base_fence as fen ,base_car as car " +
                 "WHERE tcw.person_id = per.person_id and tcw.fence_id = fen.fence_id and tcw.car_id = car.car_id  and tcw.effect_date = '" + date + "' and tcw.work_plan_type = 'car' and tcw.work_state<>0;";

            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlStr);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    int planDetailId = devDT1.Rows[i]["plan_detail_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["plan_detail_id"].ToString());
                    int work_plan_id = devDT1.Rows[i]["work_plan_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_plan_id"].ToString());
                    int work_team_id = devDT1.Rows[i]["work_team_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_team_id"].ToString());
                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    string workPlanType = devDT1.Rows[i]["work_plan_type"] == DBNull.Value ? "" : devDT1.Rows[i]["work_plan_type"].ToString();
                    string startSpan = devDT1.Rows[i]["start_span"] == DBNull.Value ? "" : devDT1.Rows[i]["start_span"].ToString();
                    string endSpan = devDT1.Rows[i]["end_span"] == DBNull.Value ? "" : devDT1.Rows[i]["end_span"].ToString();
                    int personId = devDT1.Rows[i]["person_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["person_id"].ToString());
                    string personName = devDT1.Rows[i]["person_name"] == DBNull.Value ? "" : devDT1.Rows[i]["person_name"].ToString();
                    string effectDate = devDT1.Rows[i]["effect_date"] == DBNull.Value ? "" : devDT1.Rows[i]["effect_date"].ToString();
                    string checkNames = devDT1.Rows[i]["check_names"] == DBNull.Value ? "" : devDT1.Rows[i]["check_names"].ToString();
                    string checkPoints = devDT1.Rows[i]["check_points"] == DBNull.Value ? "" : devDT1.Rows[i]["check_points"].ToString();
                    int carId = devDT1.Rows[i]["car_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["car_id"].ToString());
                    string carNum = devDT1.Rows[i]["car_num"] == DBNull.Value ? "" : devDT1.Rows[i]["car_num"].ToString();
                    int fenceId = devDT1.Rows[i]["fence_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["fence_id"].ToString());

                    ReportCheckPoint reportCheckPoint = new ReportCheckPoint();
                    reportCheckPoint.workPlanId = work_plan_id;
                    reportCheckPoint.workTeamId = work_team_id;
                    reportCheckPoint.planDetailId = planDetailId;
                    reportCheckPoint.workPlanType = workPlanType;
                    reportCheckPoint.startSpan = TimeSpan.Parse(startSpan);
                    reportCheckPoint.endSpan = TimeSpan.Parse(endSpan);
                    reportCheckPoint.personId = personId;
                    reportCheckPoint.personName = personName;
                    reportCheckPoint.effectDate = effectDate;
                    reportCheckPoint.checkNames = checkNames;
                    reportCheckPoint.checkPoints = checkPoints;
                    reportCheckPoint.deviceId = deviceId;
                    reportCheckPoint.carId = carId;
                    reportCheckPoint.carNum = carNum;
                    reportCheckPoint.points = QueryFencePoint(fenceId);

                    CalcInCheckPoint(reportCheckPoint);

                }
            }
        }



        /// <summary>
        /// 
        /// </summary>
        private static void CalcReportCheckPointPerson(string date)
        {
            string sqlStr = "SELECT tcw.plan_detail_id,tcw.work_plan_id,work_team_id,tcw.work_plan_type,tcw.person_id,per.person_name,tcw.effect_date,tcw.device_id" +
                 ", tcw.start_span,tcw.end_span,fen.check_names,fen.check_points,fen.fence_id" +
                 " FROM  report_check_work as tcw,base_person as per,base_fence as fen " +
                 " WHERE tcw.person_id = per.person_id and tcw.fence_id = fen.fence_id and tcw.effect_date = '" + date + "' and tcw.work_plan_type = 'person' and tcw.work_state <>0;";

            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlStr);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    int planDetailId = devDT1.Rows[i]["plan_detail_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["plan_detail_id"].ToString());
                    int work_plan_id = devDT1.Rows[i]["work_plan_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_plan_id"].ToString());
                    int work_team_id = devDT1.Rows[i]["work_team_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_team_id"].ToString());
                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    string workPlanType = devDT1.Rows[i]["work_plan_type"] == DBNull.Value ? "" : devDT1.Rows[i]["work_plan_type"].ToString();
                    string startSpan = devDT1.Rows[i]["start_span"] == DBNull.Value ? "" : devDT1.Rows[i]["start_span"].ToString();
                    string endSpan = devDT1.Rows[i]["end_span"] == DBNull.Value ? "" : devDT1.Rows[i]["end_span"].ToString();
                    int personId = devDT1.Rows[i]["person_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["person_id"].ToString());
                    string personName = devDT1.Rows[i]["person_name"] == DBNull.Value ? "" : devDT1.Rows[i]["person_name"].ToString();
                    string effectDate = devDT1.Rows[i]["effect_date"] == DBNull.Value ? "" : devDT1.Rows[i]["effect_date"].ToString();
                    string checkNames = devDT1.Rows[i]["check_names"] == DBNull.Value ? "" : devDT1.Rows[i]["check_names"].ToString();
                    string checkPoints = devDT1.Rows[i]["check_points"] == DBNull.Value ? "" : devDT1.Rows[i]["check_points"].ToString();
                    int fenceId = devDT1.Rows[i]["fence_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["fence_id"].ToString());

                    ReportCheckPoint reportCheckPoint = new ReportCheckPoint();
                    reportCheckPoint.workPlanId = work_plan_id;
                    reportCheckPoint.workTeamId = work_team_id;
                    reportCheckPoint.planDetailId = planDetailId;
                    reportCheckPoint.workPlanType = workPlanType;
                    reportCheckPoint.startSpan = TimeSpan.Parse(startSpan);
                    reportCheckPoint.endSpan = TimeSpan.Parse(endSpan);
                    reportCheckPoint.personId = personId;
                    reportCheckPoint.personName = personName;
                    reportCheckPoint.effectDate = effectDate;
                    reportCheckPoint.checkNames = checkNames;
                    reportCheckPoint.checkPoints = checkPoints;
                    reportCheckPoint.deviceId = deviceId;
                    reportCheckPoint.points = QueryFencePoint(fenceId);
                    reportCheckPoint.fenId = fenceId;

                    CalcInCheckPoint(reportCheckPoint);

                }
            }
        }
        private static List<CheckPoint> QueryFencePoint(int fenceId)
        {
            List<CheckPoint> points1 = new List<CheckPoint>();
            string sql = "select point_id,check_name,lat,lng from base_fence_point where fence_id = " + fenceId + "";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sql);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    string check_name = devDT1.Rows[i]["check_name"] == DBNull.Value ? "" : devDT1.Rows[i]["check_name"].ToString();
                    string lat = devDT1.Rows[i]["lat"] == DBNull.Value ? "" : devDT1.Rows[i]["lat"].ToString();
                    string lng = devDT1.Rows[i]["lng"] == DBNull.Value ? "" : devDT1.Rows[i]["lng"].ToString();
                    int point_id = devDT1.Rows[i]["point_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["point_id"].ToString());

                    var v = new CheckPoint();
                    v.pointId = point_id;
                    v.checkPoint = lat + "," + lng;
                    v.checkName = check_name;
                    v.inOut = false;
                    v.enterTime = new List<string>();
                    points1.Add(v);
                }
            }
            return points1;

        }


        static void CalcInCheckPoint(ReportCheckPoint reportCheckPoint)
        {
            string startDt = reportCheckPoint.effectDate + " " + reportCheckPoint.startSpan + ":00";
            string endDt = reportCheckPoint.effectDate + " " + reportCheckPoint.endSpan + ":00";
            string sqlStr = $"SELECT lat,lng,data_time,speed,car_location FROM `dev_gps_history` WHERE device_id={reportCheckPoint.deviceId} and data_time>'{startDt}' and data_time<'{endDt}' ORDER BY data_time asc";
            List<Point> points = new List<Point>();
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlStr);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    string lat = devDT1.Rows[i]["lat"] == DBNull.Value ? "" : devDT1.Rows[i]["lat"].ToString();
                    string lng = devDT1.Rows[i]["lng"] == DBNull.Value ? "" : devDT1.Rows[i]["lng"].ToString();
                    string dt = devDT1.Rows[i]["data_time"] == DBNull.Value ? "" : devDT1.Rows[i]["data_time"].ToString();
                    string speed = devDT1.Rows[i]["speed"] == DBNull.Value ? "0" : devDT1.Rows[i]["speed"].ToString();
                    string carLocation = devDT1.Rows[i]["car_location"] == DBNull.Value ? "0" : devDT1.Rows[i]["car_location"].ToString();
                    Point point = new Point(lng, lat);
                    point.dateTime = dt;
                    point.carLocation = carLocation;
                    point.speed = double.Parse(speed);
                    points.Add(point);
                }
            }



            Point fisrtPoint = null;
            Point fisrtPoint1 = null;
            for (int i = 0; i < points.Count - 1; i++)
            {
                double mileage = OutInAreaLineAlarm.GetTwoPointsDistance(points[i], points[i + 1]);
                double time =  (int)(DateTime.Parse(points[i+1].dateTime) - DateTime.Parse(points[i ].dateTime)).TotalMinutes;
                if (time>10)
                {
                    if (fisrtPoint != null)
                    {
                        fisrtPoint = null;
                    }
                        if (fisrtPoint1 != null)
                    {
                        fisrtPoint1 = null;
                    }
                }

                if (mileage > 200)
                {
                    if (fisrtPoint1 == null)
                    {
                        fisrtPoint1 = points[i];
                        if (reportCheckPoint.carId!=0)
                        {
                            string sql = "INSERT INTO `report_car_time`(`person_id`, `car_id`, `fence_id`, `data_time`, `start_time`, `end_time`, `running_time`, `create_by`, `create_time`) VALUES" +
                         $" ({reportCheckPoint.personId}, {reportCheckPoint.carId}, {reportCheckPoint.fenId}, '{reportCheckPoint.effectDate}', '{fisrtPoint1.dateTime}', '{fisrtPoint1.dateTime}', 0, 'tcp', now());select @@IDENTITY;";

                            fisrtPoint1.sqlInt = (UInt64)DBHelp.DBHelp.executeSql(sql);
                        }
                     
                    }
                    else
                    {
                        if (reportCheckPoint.carId != 0)
                        {
                            int stopTime = (int)(DateTime.Parse(points[i].dateTime) - DateTime.Parse(fisrtPoint1.dateTime)).TotalMinutes;
                            string update = $"update report_car_time set end_time='{points[i].dateTime}',running_time={stopTime} where time_id={fisrtPoint1.sqlInt};";
                            DBHelp.DBHelp.ExecSql(update);
                        }
                    
                    }
                }
                else
                {
                    if (fisrtPoint1 != null)
                    {
                        fisrtPoint1 = null;
                    }
                }



                reportCheckPoint.mileage += mileage;
                if (points[i].speed > 0 && points[i].speed < 10)
                {
                    if (fisrtPoint==null)
                    {
                        fisrtPoint = points[i];
                        if (reportCheckPoint.carId != 0)
                        {
                            string sql = "INSERT INTO `report_car_stop`(`person_id`, `car_id`, `fence_id`, `data_time`, `start_time`, `end_time`, `stop_time`, `start_oil`, `end_oil`, `oil_cost`, `lat`, `lng`, `address`, `create_by`, `create_time`) VALUES" +
    $" ({reportCheckPoint.personId}, {reportCheckPoint.carId}, {reportCheckPoint.fenId}, '{reportCheckPoint.effectDate}', '{fisrtPoint.dateTime}', '{fisrtPoint.dateTime}', 0, 0, 0, 0, '{fisrtPoint.getY()}', '{fisrtPoint.getX()}', '{fisrtPoint.carLocation}', NULL, NULL);select @@IDENTITY;";
                            fisrtPoint.sqlInt = (UInt64)DBHelp.DBHelp.executeSql(sql);
                        }

                    }
                    else
                    {
                        if (reportCheckPoint.carId != 0)
                        {
                            int stopTime = (int)(DateTime.Parse(points[i].dateTime) - DateTime.Parse(fisrtPoint.dateTime)).TotalMinutes;
                            string update = $"update report_car_stop set end_time='{points[i].dateTime}',stop_time={stopTime} where stop_id={fisrtPoint.sqlInt};";
                            DBHelp.DBHelp.ExecSql(update);
                        }
                      
                    }
                }
                else
                {
                    if (fisrtPoint!=null)
                    {
                        fisrtPoint = null;
                    }
                }




                foreach (var item in reportCheckPoint.points)
                {
                    bool isIn = OutInAreaLineAlarm.GetTwoPointsDistance(points[i], new Point(item.checkPoint)) < 10 ? true : false;
                    if (isIn && !item.inOut)
                    {
                        item.inOut = true;
                        //item.enterTime.Add(points[i].dateTime);
                        string sql = $"INSERT INTO  `report_check_point`(`work_plan_id`,work_team_id, `target_type`, `car_id`, `person_id`, `effect_date`, `enter_time`, `create_time`, `mileage`,point_id) VALUES " +
          $"({reportCheckPoint.workPlanId}, {reportCheckPoint.workTeamId},'{reportCheckPoint.workPlanType}', {reportCheckPoint.carId}, {reportCheckPoint.personId},  '{reportCheckPoint.effectDate}', '{points[i].dateTime}', now(), {reportCheckPoint.mileage},{item.pointId});";
                        DBHelp.DBHelp.ExecSql(sql);

                    }
                    if (!isIn && item.inOut)
                    {
                        item.inOut = false;
                    }
                }

            }

        }
        static void UpdateRedisData()
        {
            string sqlStr = "SELECT * FROM `alarm_rule`";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlStr);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {

                    int stop_max_minute = devDT1.Rows[i]["stop_max_minute"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["stop_max_minute"].ToString());

                    int out_max_minute = devDT1.Rows[i]["out_max_minute"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["out_max_minute"].ToString());
                    int oil_waste = devDT1.Rows[i]["oil_waste"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["oil_waste"]?.ToString());
                    bool enabled = devDT1.Rows[i]["enabled"] == DBNull.Value ? false : bool.Parse(devDT1.Rows[i]["enabled"].ToString());

                    string rule_target = devDT1.Rows[i]["rule_target"] == DBNull.Value ? null : devDT1.Rows[i]["rule_target"].ToString();
                    string alarm_type = devDT1.Rows[i]["alarm_type"] == DBNull.Value ? null : devDT1.Rows[i]["alarm_type"].ToString();
                    string alarm_rule_name = devDT1.Rows[i]["alarm_rule_name"] == DBNull.Value ? null : devDT1.Rows[i]["alarm_rule_name"].ToString();
                    var alarm = new AlarmRule();
                    alarm.alarm_rule_name = alarm_rule_name;
                    alarm.alarm_type = alarm_type;
                    alarm.enabled = enabled;
                    alarm.oil_waste = oil_waste;
                    alarm.out_max_minute = out_max_minute;
                    alarm.rule_target = rule_target;
                    alarm.stop_max_minute = stop_max_minute;

                    //bool a = false;
                    //do
                    //{
                    //   a=
                    redis.HashSet<AlarmRule>("AlarmRule", alarm_type, alarm);

                    //} while (!a); 
                    //Console.WriteLine(a);
                }
            }





        }

        private static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine("异常退出" + e.ExceptionObject + e.ToString());
        }

        static void UpdateInserHistory()
        {
            string sqlSelectDevice = "select * from dev_gps_history where  create_date>='2022-05-05 14:30:11' and create_date<='2022-05-06 10:29:35';";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlSelectDevice);
            StringBuilder stringBuilder = new StringBuilder();
            int j = 0;

            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {

                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    string lat = devDT1.Rows[i]["lat"] == DBNull.Value ? "" : devDT1.Rows[i]["lat"].ToString();
                    string lng = devDT1.Rows[i]["lng"] == DBNull.Value ? "" : devDT1.Rows[i]["lng"].ToString();
                    string data_time = devDT1.Rows[i]["data_time"] == DBNull.Value ? "" : devDT1.Rows[i]["data_time"].ToString();
                    string alarm_code = devDT1.Rows[i]["alarm_code"] == DBNull.Value ? "0" : devDT1.Rows[i]["alarm_code"].ToString();
                    string alarm_type = devDT1.Rows[i]["alarm_type"] == DBNull.Value ? "" : devDT1.Rows[i]["alarm_type"].ToString();
                    string hight = devDT1.Rows[i]["hight"] == DBNull.Value ? "0" : devDT1.Rows[i]["hight"].ToString();
                    string speed = devDT1.Rows[i]["speed"] == DBNull.Value ? "0" : devDT1.Rows[i]["speed"].ToString();
                    string direction = devDT1.Rows[i]["direction"] == DBNull.Value ? "0" : devDT1.Rows[i]["direction"].ToString();
                    string mileage = devDT1.Rows[i]["mileage"] == DBNull.Value ? "0" : devDT1.Rows[i]["mileage"].ToString();
                    string oil_mass = devDT1.Rows[i]["oil_mass"] == DBNull.Value ? "0" : devDT1.Rows[i]["oil_mass"].ToString();
                    string dev_state = devDT1.Rows[i]["dev_state"] == DBNull.Value ? "" : devDT1.Rows[i]["dev_state"].ToString();
                    string car_location = devDT1.Rows[i]["car_location"] == DBNull.Value ? "" : devDT1.Rows[i]["car_location"].ToString();
                    if (j > 100)
                    {
                        TDUtilsTools.ExecuteQuery(_conn, stringBuilder.ToString());
                        j = 0;

                        stringBuilder.Clear();
                    }
                    DateTime dt = DateTime.Parse(data_time);
                    string PhoneNum = _RealTimeGps[deviceId];
                    stringBuilder.Append("INSERT INTO d");
                    stringBuilder.Append(PhoneNum + $" USING dev_gps_history TAGS ( {deviceId},'{PhoneNum}') VALUES ( ");
                    stringBuilder.Append($"{GwUtil.DateTimeToUtc(dt)},now,{lat},{lng},{alarm_code},'{alarm_type}',{hight}," +
                        $"{speed},{direction},{mileage},{oil_mass},0,'{dev_state}','{car_location}');");
                    j++;
                }
            }
        }
        static void UpdateInserHistory1()
        {
            string sqlSelectDevice = "select history_id,lat,lng from dev_gps_history where  car_location='中国' ;";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlSelectDevice);
            StringBuilder stringBuilder = new StringBuilder();
            int j = 0;

            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {

                    int history_id = devDT1.Rows[i]["history_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["history_id"].ToString());
                    double lat = devDT1.Rows[i]["lat"] == DBNull.Value ? 0.00 : double.Parse(devDT1.Rows[i]["lat"].ToString());
                    double lng = devDT1.Rows[i]["lng"] == DBNull.Value ? 0.00 : double.Parse(devDT1.Rows[i]["lng"].ToString());

                    if (j > 1)
                    {
                        //TDUtilsTools.ExecuteQuery(_conn, stringBuilder.ToString());
                        DBHelp.DBHelp.ExecSql(stringBuilder.ToString());
                        j = 0;

                        stringBuilder.Clear();
                    }
                    double[] lngLat = ProjectionConvertUtil.wgs84togcj02(lng, lat);
                    double PosX = double.Parse(lngLat[0].ToString("0.000000"));
                    double PosY = double.Parse(lngLat[1].ToString("0.000000"));
                    string PlaceInfo = GetPoi(lng, lat);
                    stringBuilder.Append($"update dev_gps_history set lat='{PosY}',lng='{PosX}' , car_location='{PlaceInfo}' where history_id={history_id};");

                    j++;
                }
            }
        }

        static void ClearRedisWorkCheck()
        {
            for (int i = 40; i >= 0; i--)
            {
                DateTime dt = DateTime.Now.AddDays(-i);
                foreach (var item in _DeviceInfoAll.Keys)
                {
                    string key = dt.ToString("yyyy-MM-dd") + ":" + item;
                    var curDayTaskPlans = redis.HashValues<CurDayTaskPlan>(key);
                    foreach (var plan in curDayTaskPlans)
                    {
                        plan.workState = 0;
                        redis.HashSet<CurDayTaskPlan>(key, plan.hashKey, plan);
                    }

                }
            }
        }


        private static void DownMsgToWeb(string str)
        {
            LogHelp.WriteeLog("DownMsgToWeb", str);
            redis.Subscribe("channel:LbsApi");
            redis.Publish("channel:LbsApi", str);
            redis.Unsubscribe("channel:LbsApi");


        }


        private static void SelectDeviceInfo()
        {
            string sqlSelectDevice = "select device_id,device_phone_num,device_type from base_device ;";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlSelectDevice);

            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                lock (_DeviceInfoAll)
                {
                    _DeviceInfoAll.Clear();
                }

                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    string deviceTpe = devDT1.Rows[i]["device_type"] == DBNull.Value ? "" : devDT1.Rows[i]["device_type"].ToString();
                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    //int car_id = devDT1.Rows[i]["car_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["car_id"].ToString());
                    string deviceNo = devDT1.Rows[i]["device_phone_num"] == DBNull.Value ? "" : devDT1.Rows[i]["device_phone_num"].ToString();
                    var dev = new DeviceInfo();
                    dev.deviceId = deviceId;
                    dev.deviceType = deviceTpe;
                    dev.deviceNo = deviceNo;
                    //dev.carId = car_id;
                    lock (_DeviceInfoAll)
                    {
                        if (_DeviceInfoAll.ContainsKey(deviceNo))
                        {
                            _DeviceInfoAll[deviceNo] = dev;
                        }
                        else
                        {
                            _DeviceInfoAll.Add(deviceNo, dev);
                        }

                    }

                }
            }
        }
        private static DeviceInfo SelectDeviceInfo(string phoneNum)
        {

            var dev = new DeviceInfo();
            string sqlSelectDevice = "select device_id,device_phone_num from base_device where device_phone_num='" + phoneNum + "'  LIMIT 1 ;";
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlSelectDevice);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    //int objectId = devDT1.Rows[i]["object_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["object_id"].ToString());
                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    string deviceNo = devDT1.Rows[i]["device_phone_num"] == DBNull.Value ? "" : devDT1.Rows[i]["device_phone_num"].ToString();
                    //int car_id = devDT1.Rows[i]["car_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["car_id"].ToString());
                    dev.deviceId = deviceId;
                    //dev.objectId = objectId;
                    dev.deviceNo = deviceNo;
                    lock (_DeviceInfoAll)
                    {
                        if (_DeviceInfoAll.ContainsKey(deviceNo))
                        {
                            _DeviceInfoAll[deviceNo] = dev;
                        }
                        else
                        {
                            _DeviceInfoAll.Add(deviceNo, dev);
                        }

                    }

                }
            }
            return dev;
        }
        /// <summary>
        /// 状态显示定时器
        /// </summary>
        /// <param name="o"></param>
        private static void ShowStatus(Object o)
        {
            try
            {
                //GC.Collect();


                LogHelp.WriteeLog("ShowStatus", DateTime.Now + ",Conn:" + _PhoneSocketMap.Count + ",Hd:" + ProcessedCount + ",Undo:" + _recvPakageTcpQue.Count + ",UnDo:" + GetUnHandleDataCount() + "UnDb:" + GetRemainCount() + ",UnSd:" + _sendPakageTcpQue.Count + ",UnPhoto:" + MultiMediaDic.Count);

                Thread sendMsg = new Thread(new ThreadStart(UpateData));
                sendMsg.Start();

            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("ShowStatusException", ex.ToString());
            }
        }

        private static void UpateData()
        {
            try
            {
                string updateAlarm = "update alarm_event set event_finish=1 where event_finish=0  and TIMESTAMPDIFF(MINUTE,event_end,now())>30";
                DBHelp.DBHelp.ExecSql(updateAlarm);


                var nowDt = DateTime.Now;
                TimeSpan ts = nowDt - _nowDt;
                if (ts.TotalMinutes > 5)
                {
                    SelectDeviceInfo();
                    _nowDt = nowDt;
                }
                if (nowDt.Hour == 00 && nowDt.Minute > 58)
                {
                    SelectCurDayTaskPlan("person");
                    SelectCurDayTaskPlan("car");

                    string updateSql = $" update report_check_work set absence_reason='未上线' WHERE work_state=0 and effect_date='{DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}';";
                    DBHelp.DBHelp.ExecSql(updateSql);
                }
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("UpateData", ex.ToString());
            }
        }

        private static string GetUnHandleDataCount()
        {
            string ret = "";
            for (int i = 0; i < _handleDataList.Count; i++)
            {
                ret += _handleDataList[i].Count + ",";
            }
            return ret;
        }

        private static int GetRemainCount()
        {
            int ret = 0;
            for (int i = 0; i < 1; i++)
            {
                lock (_insertSqlList[i])
                {
                    ret += _insertSqlList[i].Count;
                }
            }
            return ret;
        }
        private static void InitHandleDataList()
        {
            _handleDataList.Clear();
            _lockHandleList.Clear();
            for (int i = 0; i < 10; i++)
            {
                Queue<HandleData808> qu = new Queue<HandleData808>();
                _handleDataList.Add(qu);
                object lk = new object();
                _lockHandleList.Add(lk);
            }
        }
        private static void InitGpsList()
        {
            _insertSqlList.Clear();
            for (int i = 0; i < 1; i++)
            {
                Queue<Gps> gps = new Queue<Gps>();
                _insertSqlList.Add(gps);
            }
        }

        /// <summary>
        /// 初始化可用的消息ID
        /// </summary>
        private static void InitMsgId()
        {
            HashMsgID.Clear();
            HashMsgID.Add("0001", "");
            HashMsgID.Add("0002", "");
            HashMsgID.Add("0003", "");
            HashMsgID.Add("0100", "");
            HashMsgID.Add("0101", "");
            HashMsgID.Add("0102", "");
            HashMsgID.Add("0120", "");
            HashMsgID.Add("0107", "");
            HashMsgID.Add("0200", "");
            HashMsgID.Add("0500", "");
            HashMsgID.Add("6002", "");
            HashMsgID.Add("0201", "");
            HashMsgID.Add("6006", "");
            HashMsgID.Add("0801", "");
            HashMsgID.Add("0805", "");
            HashMsgID.Add("0104", "");
            HashMsgID.Add("0702", "");
            HashMsgID.Add("0701", "");
            HashMsgID.Add("0900", "");
            HashMsgID.Add("0800", "");
            HashMsgID.Add("0301", "");
            HashMsgID.Add("0302", "");
            HashMsgID.Add("0303", "");
            HashMsgID.Add("8304", "");
            HashMsgID.Add("0901", "");
            HashMsgID.Add("6005", "");
            HashMsgID.Add("0802", "");
            HashMsgID.Add("0700", "");
            HashMsgID.Add("0704", "");
            HashMsgID.Add("0013", "");
            HashMsgID.Add("0004", "");
            HashMsgID.Add("0006", "");
            HashMsgID.Add("0009", "");
        }

        /// <summary>
        /// 判断消息ID是否是合法的
        /// </summary>
        /// <param name="totalbuffers"></param>
        /// <param name="readIndex"></param>
        /// <returns></returns>
        private static bool IsMsgIdOk(byte[] totalbuffers, int readIndex)
        {
            if (totalbuffers.Length < readIndex + 2 + 1) return false;
            return true;
            //List<byte> blist = new List<byte>();
            //blist.Add(totalbuffers[readIndex + 1]);
            //blist.Add(totalbuffers[readIndex + 2]);

            //var msgId = GwUtil.BytesToHex(blist.ToArray());
            //return HashMsgID.Contains(msgId);
        }

        #region 初始化并启动所有工作线程
        private static void InitAndStartThreads()
        {
            Thread sendMsg = new Thread(new ThreadStart(CreateSubscription));
            sendMsg.Start();


            Thread sendMsg1 = new Thread(new ThreadStart(CreateSubscription1));
            sendMsg1.Start();

            for (int i = 0; i < 1; i++)
            {
                Thread trdHandleOneDataThread = new Thread(new ThreadStart(ThreadTcpRecvFromPakageProc));
                trdHandleOneDataThread.Start();
            }
            for (int i = 0; i < 1; i++)
            {
                Thread trdTcpSendThread = new Thread(new ThreadStart(ThreadTcpSendPakageProc));
                trdTcpSendThread.Start();
            }
            for (int i = 0; i < 1; i++)
            {
                Thread tInsert = new Thread(new ThreadStart(ThreadProcInsertGps));
                tInsert.Start();
            }

            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ParameterizedThreadStart(ThreadHandleDataProc));
                thread.Start((object)i);
            }
            for (int i = 0; i < 1; i++)
            {
                Thread tUpSql = new Thread(new ThreadStart(ThreadProcUpdateSql));
                tUpSql.Start();
            }

            Thread tUp0306 = new Thread(new ThreadStart(setRedisGpsCache));
            tUp0306.Start();


        }

        /// <summary>
        ///  使用redis向设备下发消息
        /// </summary>
        private static void CreateSubscription()
        {
            ISubscriber sub = redis._conn.GetSubscriber();
            Action<RedisChannel, RedisValue> handler = null;
            sub.Subscribe("DownSendDeviceChannel_808", (channel, message) =>
            {
                if (handler == null)
                {
                    try
                    {
                        string msg = message.ToString();

                        msg = msg.TrimStart('\"');
                        msg = msg.TrimEnd('\"');
                        msg = msg.Replace("\\", "");
                        LogHelp.WriteeLog("CreateSubscription", "DownSendDeviceChannel_808" + " 订阅收到消息：" + msg);

                        List<Dictionary<string, string>> lt1 = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(msg);
                        msg = null;
                        SendMsgServer sendMsg = new SendMsgServer();

                        sendMsg.SendMessage(lt1);
                        lt1.Clear();
                        lt1 = null;
                    }
                    catch (Exception ex)
                    {

                        LogHelp.WriteeLog("CreateSubscription", ex.ToString());
                    }

                }
                else
                {
                    handler(channel, message);
                }
            });

        }
        private static void CreateSubscription1()
        {
            ISubscriber sub = redis._conn.GetSubscriber();
            Action<RedisChannel, RedisValue> handler = null;
            sub.Subscribe("WatchLocationChannel", (channel, message) =>
            {
                if (handler == null)
                {
                    try
                    {
                        string msg = message.ToString();

                        msg = msg.TrimStart('\"');
                        msg = msg.TrimEnd('\"');
                        msg = msg.Replace("\\", "");
                        LogHelp.WriteeLog("WatchLocationChannel" , " 订阅收到消息：" + msg);

                        BraceletLocation bracelet = JsonConvert.DeserializeObject<BraceletLocation>(msg);
                        DeviceInfo device = null;
                        lock (_DeviceInfoAll)
                        {
                            if (_DeviceInfoAll.ContainsKey(bracelet.deviceid))
                            {
                                device = _DeviceInfoAll[bracelet.deviceid];
                            }
                        }
                        if (device==null)
                        {
                            device = SelectDeviceInfo(bracelet.deviceid);
                        }



                        if (device != null)
                        {
                            lock (_RealTimeGps)
                            {
                                if (!_RealTimeGps.ContainsKey(device.deviceId))
                                {
                                    string sqlStr = $"insert into dev_gps_realtime (device_id,device_phone_num)value({device.deviceId},'{device.deviceNo}');";
                                    DBHelp.DBHelp.ExecSql(sqlStr);
                                    _RealTimeGps.Add(device.deviceId, device.deviceNo);

                                }
                            }
                            Gps gps = new Gps(bracelet);
                            gps.deviceId = device.deviceId.ToString();
                            CalcCheckWork(gps, "work_card");


                        }

                    

                    }
                    catch (Exception ex)
                    {

                        LogHelp.WriteeLog("CreateSubscription1", ex.ToString());
                    }

                }
                else
                {
                    handler(channel, message);
                }
            });

        }
        #region 解析一个完整TCP数据
        private static void ThreadTcpRecvFromPakageProc()
        {
            while (true)
            {
                SourceData bs = null;
                try
                {
                    bs = PopSourceData();
                    if (bs != null)
                    {
                        HandleOne808Package(bs);
                    }
                    else
                    {
                        Thread.Sleep(2);
                    }
                }
                catch (Exception e)
                {

                    LogHelp.WriteeLog("ThreadTcpRecvFromPakageProc：", e.ToString() + "data:" + (bs == null ? "null" : GwUtil.BytesToHex(bs.bs)));
                }
                finally
                {
                    bs = null;
                }
            }

        }
        #endregion

        #region 下发TCP数据
        private static void ThreadTcpSendPakageProc()
        {
            while (true)
            {
                SourceData bs = null;
                try
                {
                    bs = PopSend();
                    if (bs != null)
                    {
                        server.Send(bs.Client, bs.bs, bs.bs.Length);
                        LogHelp.WriteLog(GwUtil.BytesToHex(bs.bs), "发送", bs.deviceNo);
                    }
                    else
                    {
                        Thread.Sleep(2);
                    }
                }
                catch (Exception e)
                {

                    LogHelp.WriteeLog("", "ThreadTcpSendPakageProc：" + e.Message + "data:" + bs == null ? "null" : GwUtil.BytesToHex(bs.bs));
                }
                finally
                {
                    bs = null;
                }
            }

        }
        #endregion

        #region 保存历史轨迹
        public static void ThreadProcInsertGps()
        {
            int count = 1000;
            while (true)
            {
                try
                {
                    for (int i = 0; i < 1; i++)
                    {
                        List<Gps> ltall = PopGps(i, count);
                        if (ltall.Count > 0)
                        {
                            var sql = ltGpsToSql(ltall);
                            DBHelp.DBHelp.ExecSql(sql);
                            sql = ltGpsToSqlNew(ltall);
                            TDUtilsTools.ExecuteQuery(_conn, sql);
                            ltall.Clear();
                            ltall = null;
                            sql = null;
                            //string sqlStr = ltGpsToSql(ltall);
                            //AddToUpdateSqlList(sqlStr);

                            //WcfTool.InsertGpsToDB(ltall);

                        }
                        else
                        {
                            Thread.Sleep(5);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("", "保存历史轨迹出错：" + ex.ToString());
                }
            }
        }
        #endregion
        public static void ThreadProcUpdateSql()
        {
            string sql = string.Empty;
            while (true)
            {
                try
                {
                    sql = PopFromUpdateSqlList();
                    if (sql == string.Empty)
                    {
                        Thread.Sleep(2);
                    }
                    else
                    {
                        //WcfTool.UpdateToDB(sql);
                        string result1 = DBHelp.DBHelp.ExecSql(sql);
                        if (result1.Contains("执行sql"))
                        {
                            LogHelp.WriteeLog("ThreadProcUpdateSql", result1);
                        }
                        result1 = null;
                    }
                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("ThreadProcUpdateSql", ex.ToString());
                }
                finally
                {
                    sql = null;
                }

            }
        }
        private static void ThreadHandleDataProc(object obj)
        {
            int flag = (int)obj;
            LogHelp.WriteeLog("ThreadHandleDataProc", "数据处理线程参数=" + flag);
            while (true)
            {
                HandleData808 data = null;//打印错误data
                try
                {
                    //HandleData808 data = PopHandleData(flag);
                    data = PopHandleData(flag);
                    if (data != null)
                    {
                        Analysis(data);
                        lock (ProcessedCountObj) { ProcessedCount++; }
                    }
                    else
                    {
                        Thread.Sleep(2);
                    }
                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("解析数据出错：", ex.ToString() + "--错误代码--" + ex.Message + "data:" + (data == null ? "null" :"手机号:"+data.phoneNumber+","+ GwUtil.BytesToHex(data.allbs)));
                }
                finally
                {
                    data = null;
                }
            }

        }
        private static void setRedisGpsCache()
        {
            while (true)
            {
                try
                {
                    lock (_redisGpsCacheQ)
                    {
                        if (_redisGpsCacheQ.Count > 0)
                        {
                            GpsInfo gpsInfo = _redisGpsCacheQ.Dequeue();
                            redis.HashSet<GpsInfo>("GpsInfo", gpsInfo.DeviceNo, gpsInfo);
                            gpsInfo = null;
                        }
                        else
                        {
                            Thread.Sleep(2);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("缓存Redis的GPS数据出错：", ex.Message);
                }

            }
        }
        #endregion

        #region 初始化TCP服务器
        private static void InitTcpServer()
        {
            try
            {
                server.MaxConnectionCount = 100000;
                server.OnPrepareListen += OnPrepareListen;
                server.OnAccept += OnAccept;
                server.OnSend += OnSend;

                server.OnReceive += OnReceive;

                server.OnClose += OnClose;
                server.OnShutdown += OnShutdown;
                //server.KeepAliveInterval = 0;
                //server.KeepAliveTime = 0;
                SetAppState(AppState.Stoped);

                string ip = "0.0.0.0";

                // 写在这个位置是上面可能会异常
                SetAppState(AppState.Starting);
                server.Address = ip;
                server.Port = TcpPort;
                // 启动服务
                if (server.Start())
                {
                    SetAppState(AppState.Started);
                    LogHelp.WriteeLog("InitTcpServer", string.Format("$Server Start OK -> ({0}:{1})", ip, TcpPort));
                }
                else
                {
                    SetAppState(AppState.Stoped);
                    throw new Exception(string.Format("$Server Start Error -> {0}({1})", server.ErrorMessage, server.ErrorCode));
                }
            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("InitTcpServer", "初始化TCP服务器失败。" + ex.Message);
            }
        }

        static void SetAppState(AppState state)
        {
            appState = state;
        }

        static HandleResult OnPrepareListen(HPSocket.IServer sender, IntPtr soListen)
        {
            // 监听事件到达了,一般没什么用吧?
            return HandleResult.Ok;
        }

        static HandleResult OnAccept(HPSocket.IServer sender, IntPtr connId, IntPtr pClient)
        {
            // 客户进入了
            // 获取客户端ip和端口
            //string ip = string.Empty;
            //ushort port = 0;

            //if (server.GetRemoteAddress(connId, out var ip, out var port))
            //{
            //    if (ip.ToString().Equals("211.138.113.43"))
            //    {
            //        return HandleResult.Error;
            //    }
            //    LogHelp.WriteeLog("OnAccept", string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", connId, ip.ToString(), port));
            //    //Console.WriteLine(string.Format(" > [{0},OnAccept] -> PASS({1}:{2})", connId, ip.ToString(), port));
            //}
            //else
            //{
            //    LogHelp.WriteeLog("OnAccept", string.Format(" > [{0},OnAccept] -> Server_GetClientAddress() Error", connId));
            //}


            //ClientInfo clientInfo = new ClientInfo();
            //clientInfo.ConnId = connId;
            //clientInfo.IpAddress = ip;
            //clientInfo.Port = port;




            return HandleResult.Ok;
        }

        static HandleResult OnSend(HPSocket.IServer sender, IntPtr connId, byte[] bytes)
        {
            // 服务器发数据了
            return HandleResult.Ok;
        }

        static HandleResult OnReceive(HPSocket.IServer sender, IntPtr connId, byte[] bytes)
        {
            // 数据到达了
            try
            {


                if (bytes.Length > 0)
                {
                    byte[] bs = new byte[bytes.Length];
                    Buffer.BlockCopy(bytes, 0, bs, 0, bytes.Length);
                    HandlePackages(bs, connId);
                    bytes = null;
                    bs = null;
                    //WriteeLog(GwUtil.BytesToHex(bs));
                }
                return HandleResult.Ok;
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("OnReceive", ex.ToString());
                return HandleResult.Ignore;
            }
        }
        static HandleResult OnClose(HPSocket.IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode)
        {
            if (errorCode == 0)
            {
                //LogHelp.WriteeLog("OnClose", string.Format(" > [{0},OnClose]", connId));
            }
            else
            {
                LogHelp.WriteeLog("OnClose", string.Format(" > [{0},OnError] -> OP:{1},CODE:{2}", connId, enOperation, errorCode));
            }
            RtDataCache.Instance.DisconnectClear(connId.ToString());
            DeviceInfo device = null;
            lock (_DevOnlineRecordInfo)
            {
                if (_DevOnlineRecordInfo.ContainsKey(connId))
                {
                    device = _DevOnlineRecordInfo[connId];
                    _DevOnlineRecordInfo.Remove(connId);
                }
            }
            if (device != null)
            {
                lock (_PhoneSocketMap)
                {
                    if (_PhoneSocketMap.ContainsKey(device.deviceNo))
                    {
                        _PhoneSocketMap.Remove(device.deviceNo);
                    }

                }
                string sql = $"update dev_online_record set end_time=now(),online_state=2 where online_state=1 and device_id={device.deviceId};";
                DBHelp.DBHelp.ExecSql(sql);
            }







            return HandleResult.Ok;
        }

        static HandleResult OnShutdown(HPSocket.IServer sender)
        {
            // 服务关闭了
            LogHelp.WriteeLog("OnShutdown", " > [OnShutdown]");
            return HandleResult.Ok;
        }
        #endregion

        /// <summary>
        /// 处理粘包问题
        /// </summary>
        /// <param name="buffers"></param>
        /// <param name="client"></param>
        private static void HandlePackages(byte[] buffers, IntPtr client)
        {

            byte[] totalbuffers = null;
            var rtCach = RtDataCache.Instance;
            var waitBuffers = rtCach.GetWaitBuffers(client.ToString());

            if (waitBuffers != null && waitBuffers.Length > 0)
            {
                var waitLength = waitBuffers.Length;
                var receiveLength = buffers.Length;
                totalbuffers = new byte[receiveLength + waitLength];
                Buffer.BlockCopy(waitBuffers, 0, totalbuffers, 0, waitLength);
                Buffer.BlockCopy(buffers, 0, totalbuffers, waitLength, receiveLength);
            }
            else
            {
                totalbuffers = buffers;
            }

            //转义后：剩余包长度
            var remainLength = totalbuffers.Length;
            var readIndex = 0;

            //有些设备 7E未进行转义 重试一次
            var isTryed = false;


            List<byte> ll = new List<byte>();
            // 剩余包 够一个完整包
            while (remainLength >= MessageheadLength)
            {

                if (!totalbuffers[readIndex].Equals(0x7E) || !IsMsgIdOk(totalbuffers, readIndex))
                {
                    LogHelp.WriteeLog("", string.Format("剔除[readIndex = {0}],[value = {1}] ", readIndex, totalbuffers[readIndex]));
                    ll.Add(totalbuffers[readIndex]);
                    //剔除干扰数据
                    readIndex++;
                    remainLength--;
                    continue;
                }
                if (ll.Count > 0)
                    LogHelp.WriteeLog("HandlePackages", "剔除干扰数据：" + GwUtil.BytesToHex(ll.ToArray()));
                ll.Clear();
                //消息体属性
                string property = GwUtil.ToBin16(totalbuffers, readIndex + 3, 16);
                //是否包含分包
                var subPackage = property[2] == '1';
                //消息体长度
                var bodyLength = Convert.ToInt32(property.Substring(6), 2);
                //数据包长度
                var dataLength = bodyLength + MessageheadLength + (subPackage ? 4 : 0);

                //剩余消息体不够一个完整包 退出
                if (dataLength > remainLength) break;

                //构造完整消息体
                var dataBuffers = new byte[dataLength];
                Buffer.BlockCopy(totalbuffers, readIndex, dataBuffers, 0, dataLength);

                //7E <-->7E 校验CRC
                if (dataBuffers.Last().Equals(0x7E)
                    && GwUtil.ValidateCheckCode(dataBuffers))
                {
                    //处理消息
                    //这里处理完，一个完整消息
                    //WriteLog(GwUtil.BytesToHex(dataBuffers), "接收");
                    SourceData sd = new SourceData();
                    sd.bs = dataBuffers;
                    sd.Client = client;
                    PushSourceData(sd);

                    readIndex += dataLength;
                    remainLength -= dataLength;
                    isTryed = false;
                }
                else
                {
                    if (isTryed)
                    {
                        //LogHelper.Debug("isTryed[01]. {0},{1}", connection.ConnectionID, isTryed);
                        //已经重试过，重置
                        isTryed = false;
                        readIndex += dataLength;
                        remainLength -= dataLength;

                        LogHelp.WriteeLog("HandlePackages", string.Format("wrong. handle={0},data={1}", client.ToString(),
                             GwUtil.BytesToHex(dataBuffers)));
                        //校验码错误，断开链路，让设备重连
                        server.Disconnect(client);
                        RtDataCache.Instance.DisconnectClear(client.ToString());

                        break;
                    }
                    else
                    {
                        //LogHelper.Debug("isTryed[01]. {0},{1}", connection.ConnectionID, isTryed);
                        //未重试过，需要进行重试一次。
                        //校验码错误，有的设备没有正向7E转换
                        remainLength -= dataBuffers.Length;
                        var curlen = dataBuffers.Length;
                        while (GwUtil.ProcessTransferredRequest(dataBuffers).Length < dataLength)
                        {
                            if (remainLength > 0)
                            {
                                dataBuffers = new byte[curlen + 1];
                                Buffer.BlockCopy(totalbuffers, readIndex, dataBuffers, 0, dataBuffers.Length);
                                remainLength--;
                                curlen++;
                            }
                            else
                            {
                                break;
                            }
                        }
                        //LogHelper.Debug("ProcessTransferredRequest[02]. {0},{1}", connection.ConnectionID, FormatUtil.BytesToHexStr(dataBuffers));

                        dataBuffers = GwUtil.ProcessTransferredRequest(dataBuffers);
                        byte[] tmpBuffers = new byte[dataBuffers.Length + remainLength];
                        Buffer.BlockCopy(dataBuffers, 0, tmpBuffers, 0, dataBuffers.Length);
                        Buffer.BlockCopy(totalbuffers, totalbuffers.Length - remainLength, tmpBuffers,
                            dataBuffers.Length, remainLength);
                        totalbuffers = tmpBuffers;
                        remainLength = totalbuffers.Length;
                        readIndex = 0;
                        isTryed = true;
                        continue;
                    }
                }
            }

            //未处理完的数据包
            if (remainLength > 0)
            {
                var remainBuffers = new byte[remainLength];
                Buffer.BlockCopy(totalbuffers, readIndex, remainBuffers, 0, remainLength);
                //重设缓冲区
                rtCach.AddWaitBuffers(client.ToString(), remainBuffers);
            }
            else
            {
                //读完重设缓冲区 为空
                rtCach.AddWaitBuffers(client.ToString(), null);
            }



        }

        /// <summary>
        /// 处理一个数据包
        /// </summary>
        /// <param name="sd"></param>
        private static void HandleOne808Package(SourceData sd)
        {
            string log = "";
            try
            {

                byte[] bs = sd.bs;

                if (bs.First().Equals(0x7E) && bs.Last().Equals(0x7E) && GwUtil.ValidateCheckCode(bs))//
                {
                    //消息ID
                    int msgId = GwUtil.ToInt16(bs, 1);
                    if (msgId < 0)
                    {
                        msgId += 0x10000;
                    }
                    //终端手机号
                    byte[] bsPhoneNum = new byte[6];
                    Buffer.BlockCopy(bs, 5, bsPhoneNum, 0, 6);
                    string phoneNumber = GwUtil.BytesToHex(bsPhoneNum).TrimStart('0');

                    LogHelp.WriteLog(GwUtil.BytesToHex(sd.bs), "接收", phoneNumber);
                    //log = "11111111111111";
                    //消息流水号
                    byte[] bsSeqId = new byte[2];
                    Buffer.BlockCopy(bs, 11, bsSeqId, 0, 2);
                    int seqId = GwUtil.HexToInt(GwUtil.BytesToHex(bsSeqId));
                    //消息体属性
                    string property = GwUtil.ToBin16(bs, 3, 16);
                    //加密标志
                    int encry = property[5] == '1' ? 1 : 0;
                    //多媒体标识
                    bool multiMedia = property[0] == '1';
                    //数据是否分包
                    bool subPackage = property[2] == '1';
                    //消息体长度
                    int bodyLength = Convert.ToInt32(property.Substring(6), 2);
                    byte[] bodyBuffer = new byte[bodyLength];
                    ushort totalPacket = 0;
                    ushort curPacket = 0;
                    if (subPackage)
                    {
                        //总包数
                        totalPacket = (UInt16)GwUtil.ToInt16(bs, 13);
                        //当前包数目
                        curPacket = (UInt16)GwUtil.ToInt16(bs, 15);
                        Buffer.BlockCopy(bs, 17, bodyBuffer, 0, bodyLength);
                    }
                    else
                    {
                        Buffer.BlockCopy(bs, 13, bodyBuffer, 0, bodyLength);
                    }


                    //log = "22222222222222222222";
                    lock (_PhoneSocketMap)
                    {
                        _PhoneSocketMap[phoneNumber] = sd.Client;
                    }



                    HandleData808 data = new HandleData808();
                    data.phoneNumber = phoneNumber;
                    data.msgId = msgId;
                    data.seqId = seqId;
                    data.encry = encry;
                    data.subPackage = subPackage;
                    data.multiMedia = multiMedia;
                    data.bodyLength = bodyLength;
                    data.totalPacket = totalPacket;
                    data.curPacket = curPacket;
                    data.body = bodyBuffer;
                    data.client = sd.Client;
                    data.allbs = bs;
                    if (msgId == 0x0100)
                    {
                        PushHandleData(data);
                        return;
                    }
                    //log = "33333333333333333333";
                    DeviceInfo device = null;
                    lock (_DeviceInfoAll)
                    {
                        if (_DeviceInfoAll.ContainsKey(data.phoneNumber))
                        {
                            device = _DeviceInfoAll[data.phoneNumber];
                        }
                    }
                    //log = "4444444444444444444444";
                    if (device != null)
                    {
                        data.deviceInfo = device;

                        bool b = false;
                        lock (_DevOnlineRecordInfo)
                        {
                            if (_DevOnlineRecordInfo.ContainsKey(sd.Client))
                            {
                                b = true;
                            }
                            else
                            {
                                _DevOnlineRecordInfo.Add(sd.Client, device);
                            }
                        }
                        //log = "55555555555555";
                        if (!b)
                        {
                            string sqlStr = $"insert into dev_online_record (device_id,device_phone_num,start_time,end_time,create_time,online_state)value({device.deviceId},'{device.deviceNo}',now(),now(),now(),1);";
                            DBHelp.DBHelp.ExecSql(sqlStr);
                        }
                        //log = "666666666666666666";
                        lock (_RealTimeGps)
                        {
                            if (!_RealTimeGps.ContainsKey(device.deviceId))
                            {
                                string sqlStr = $"insert into dev_gps_realtime (device_id,device_phone_num)value({device.deviceId},'{device.deviceNo}');";
                                DBHelp.DBHelp.ExecSql(sqlStr);

                                _RealTimeGps.Add(device.deviceId, device.deviceNo);


                            }
                        }
                        log = "777777777777777777777";
                        if (msgId == 0x0200)
                        {
                            log = "999999999999999999";
                            if ("portable_locator".Equals(device.deviceType))
                            {
                                log = "111111111111111111111";
                                TransDataWorkerHY._needToTransDataList.Enqueue(bs);
                                log = "222222222222222";
                            }
                            if (device == null && device.deviceType == null)
                            {
                                log = "3333333333333333333333";
                            }
                        }

                        log = "888888888888888888";
                        PushHandleData(data);
                    }
                    else
                    {
                        LogHelp.WriteeLog("无法识别的设备数据:", data.phoneNumber + ",data:" + GwUtil.BytesToHex(sd.bs));
                    }





                }
                else
                {
                    LogHelp.WriteeLog("校验码错误:", GwUtil.BytesToHex(bs));
                }
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("HandleOne808Package", log+ ex.ToString()+ "data:" + (sd.bs == null ? "null" : GwUtil.BytesToHex(sd.bs)));
            }
        
        }

        private static void PushHandleData(HandleData808 data)
        {
            int flag = GwUtil.HexToInt(data.phoneNumber.Substring(data.phoneNumber.Length - 1, 1));
            lock (_lockHandleList[flag]) { _handleDataList[flag].Enqueue(data); }
        }
        private static HandleData808 PopHandleData(int flag)
        {
            if (flag < 0 || flag >= 16) return null;
            lock (_lockHandleList[flag])
            {
                if (_handleDataList[flag].Count > 0)
                    return _handleDataList[flag].Dequeue();
                else
                    return null;
            }
        }
        private static void PushSourceData(SourceData data)
        {

            try
            {
                lock (_lockRecvQue)
                {
                    _recvPakageTcpQue.Enqueue(data);
                }
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("PushSourceData ", ex.Message + GwUtil.BytesToHex(data.bs));
            }

        }
        private static SourceData PopSourceData()
        {

            try
            {
                lock (_lockRecvQue)
                {
                    if (_recvPakageTcpQue.Count > 0)
                        return _recvPakageTcpQue.Dequeue();
                    else
                        return null;
                }
            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("PopSourceData ", ex.Message);
                return null;
            }

        }
        private static void PushSend(SourceData data)
        {

            try
            {
                lock (_lockSendQue)
                {
                    _sendPakageTcpQue.Enqueue(data);
                }
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("PushSend ", ex.Message + GwUtil.BytesToHex(data.bs));
            }

        }
        private static SourceData PopSend()
        {

            try
            {
                lock (_lockSendQue)
                {
                    if (_sendPakageTcpQue.Count > 0)
                        return _sendPakageTcpQue.Dequeue();
                    else
                        return null;
                }
            }
            catch
            {
                return null;
            }

        }
        private static void PushGps(Gps data)
        {
            try
            {
                int flag = 0/*int.Parse(data.PhoneNum.Substring(data.PhoneNum.Length - 2, 2))*/;
                lock (_insertSqlList[flag]) { _insertSqlList[flag].Enqueue(data); }
            }
            catch (Exception ex)
            {

                LogHelp.WriteeLog("PushSql ", ex.Message + data.ToString());
            }
        }

        private static List<Gps> PopGps(int flag, int count)
        {
            //if (flag < 0 || flag >= 1) return null;
            List<Gps> ltall = new List<Gps>();
            lock (_insertSqlList[flag])
            {
                while (_insertSqlList[flag].Count > 0)
                {
                    ltall.Add(_insertSqlList[flag].Dequeue());
                }
            }
            return ltall;
            //if (ltall.Count > 0)
            //{
            //    string sqlStr = ltGpsToSql(ltall);
            //    DBHelp.DBHelp.ExecSql(sqlStr);
            //}
            //lock (_insertSqlList[flag])
            //{
            //    List<Gps> lt = new List<Gps>();
            //    for (int i = 0; i < count; i++)
            //    {
            //        if (_insertSqlList[flag].Count > 0)
            //        {
            //            Gps gps = _insertSqlList[flag].Dequeue();
            //            if (gps != null)
            //                lt.Add(gps);
            //            else
            //                break;
            //        }
            //        else
            //            break;

            //    }
            //    if (lt.Count > 0)
            //        return lt;
            //    else
            //        return null;
            //}
        }
        private static void AddToUpdateSqlList(string sql)
        {
            lock (UpdateSqlList)
            {
                UpdateSqlList.Add(sql);
            }
        }
        private static string PopFromUpdateSqlList()
        {

            StringBuilder sb = new StringBuilder();
            List<string> lt = new List<string>();
            lock (UpdateSqlList)
            {
                if (UpdateSqlList.Count > 100)
                {
                    lt = UpdateSqlList.Take(100).ToList();
                    UpdateSqlList.RemoveRange(0, 100);

                }
                else
                {
                    lt = UpdateSqlList.Take(UpdateSqlList.Count).ToList();
                    UpdateSqlList.Clear();
                }
            }
            if (lt.Count > 0)
            {
                for (int i = 0; i < lt.Count; i++)
                {
                    sb.AppendLine(lt[i]);
                }
            }
            else
                Thread.Sleep(5);
            return sb.ToString();
            //string sql = string.Empty;
            //lock (UpdateSqlList)
            //{
            //    if (UpdateSqlList.Count > 0)
            //    {
            //        sql = UpdateSqlList[0];
            //        UpdateSqlList.RemoveAt(0);
            //    }
            //}
            //return sql;
        }
        public static int SendTcpToPhone(byte[] data, string PhoneNum)
        {

            lock (_PhoneSocketMap)
            {
                if (_PhoneSocketMap.ContainsKey(PhoneNum))
                {
                    if (server.Send(_PhoneSocketMap[PhoneNum], data, data.Length))
                    {
                        LogHelp.WriteLog(GwUtil.BytesToHex(data), "发送", PhoneNum);
                        return 0;
                    }
                    else
                    {
                        return -1;
                    }
                }
                else
                {
                    return -1;
                }
            }
        }


        #region 终端上行协议解析

        private static void Analysis(HandleData808 data)
        {

            switch (data.msgId)
            {
                //终端通用应答
                case 0x0001: Handle0001Data(data); break;
                //终端心跳
                case 0x0002: Handle0002Data(data); break;
                //位置数据
                case 0x0200: Handle0200Data(data); break;
                //上班打卡
                case 0x0203: Handle0200Data(data); break;
                //下班打卡
                case 0x0204: Handle0200Data(data); break;
                //心跳信息
                case 0x0f01: Handle0F01Data(data); break;
                //卡片登录
                case 0x0f02: Handle0F02Data(data); break;

                //终端注销
                case 0x0003: Handle0003Data(data); break;
                //终端注册
                case 0x0100: Handle0100Data(data); break;
                //终端鉴权
                case 0x0102: Handle0102Data(data); break;

                case 0x0120: Handle0120Data(data); break;
                //按键事件上报
                case 0x0006: Handle0006Data(data); break;

                //车辆控制应答
                case 0x0500: Handle0500Data(data); break;
                //盲区补传
                case 0x6002: Handle6002Data(data); break;
                //位置信息查询应答
                case 0x0201: Handle0201Data(data); break;
                //上报文本消息
                case 0x6006: Handle6006Data(data); break;
                //多媒体事件信息上传
                case 0x0800: Handle0800Data(data); break;
                //多媒体数据上传
                case 0x0801: Handle0801Data(data); break;
                //终端拍照应答
                case 0x0805: Handle0805Data(data); break;
                //查询终端参数应答
                case 0x0104: Handle0104Data(data); break;
                //查询终端属性应答
                case 0x0107: Handle0107Data(data); break;
                //终端升级结果通知
                case 0x0108: Handle0108Data(data); break;
                //驾驶员身份信息采集上报
                case 0x0702: Handle0702Data(data); break;
                //电子运单上报
                case 0x0701: Handle0701Data(data); break;
                //数据上行透传
                case 0x0900: Handle0900Data(data); break;
                //事件报告
                case 0x0301: Handle0301Data(data); break;
                //提问应答
                case 0x0302: Handle0302Data(data); break;
                //信息点播
                case 0x0303: Handle0303Data(data); break;
                //信息服务
                case 0x8304: Handle8304Data(data); break;
                //数据压缩上传
                case 0x0901: Handle0901Data(data); break;
                //上报司机退登消息
                case 0x6005: Handle6005Data(data); break;
                //存储多媒体数据检索应答
                case 0x0802: Handle0802Data(data); break;
                //行驶记录数据上传
                case 0x0700: Handle0700Data(data); break;
                //新北斗盲点补传
                case 0x0704: Handle0704Data(data); break;
                //CAN总线数据上传
                case 0x0705: Handle0705Data(data); break;
                //终端上传音视频属性
                case 0x1003: Handle1003Data(data); break;
                //终端上传乘客流量
                case 0x1005: Handle1005Data(data); break;
                //终端上传音视频资料列表 应答指令
                case 0x1205: Handle1205Data(data); break;
                //文件上传完成通知 应答指令
                case 0x1206: Handle1206Data(data); break;
                    //数据中心下发指令给设备
                    // case 0x9999: Handle9999Data(data); break;

            }

        }
        private static void Handle0006Data(HandleData808 data)
        {
            int type = data.body[0];
            int touchCount = data.body[1];
            LogHelp.WriteeLog("按键事件上报", "，按键：" + type + "，次数：" + touchCount);

        }
        private static void Handle0120Data(HandleData808 data)
        {
            string iccid = GwUtil.Bytes2String(data.body, 0, 20);
            LogHelp.WriteeLog("Handle0120Data", data.phoneNumber + ":0120:ICCID:" + iccid);


            byte[] setBuffers = GwUtil.BuildPackage(0x8120, data.phoneNumber, "");
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);


        }

        private static void Handle0F02Data(HandleData808 data)
        {
            string iccid = GwUtil.BytesToHex(data.body.Skip(0).Take(10).ToArray());
            string content = GwUtil.Bytes2String(data.body, 11, data.body[10]);

            LogHelp.WriteeLog("Handle0F02Data", data.phoneNumber + "，iccid:" + iccid + "-" + content);
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(data.msgId, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.deviceNo = data.phoneNumber;
            sd.Client = data.client;
            PushSend(sd);



        }

        private static void DownSendUpdateIP(IntPtr intPtr, string phoneNumber)
        {
            if (server.GetRemoteAddress(intPtr, out var ip, out var port))
            {
                if (ip == "47.92.131.206")
                {
                    List<Dictionary<string, string>> keyValues = new List<Dictionary<string, string>>();
                    Dictionary<string, string> dic = new Dictionary<string, string>();
                    dic.Add("IMEI", phoneNumber);
                    dic.Add("CMD", "8103");
                    dic.Add("PARAM1", "2");
                    dic.Add("PARAM2", "0013|36.134.79.195");
                    dic.Add("PARAM3", "0018|8030");
                    keyValues.Add(dic);
                    new SendMsgServer().SendMessage(keyValues);

                    List<Dictionary<string, string>> keyValues1 = new List<Dictionary<string, string>>();
                    Dictionary<string, string> dic1 = new Dictionary<string, string>();
                    dic1.Add("IMEI", phoneNumber);
                    dic1.Add("CMD", "8300");
                    dic1.Add("PARAM1", "1");
                    dic1.Add("PARAM2", "#2014*SET*T:36.134.79.195,8030#");
                    keyValues1.Add(dic1);
                    new SendMsgServer().SendMessage(keyValues1);

                    List<Dictionary<string, string>> keyValues2 = new List<Dictionary<string, string>>();
                    Dictionary<string, string> dic2 = new Dictionary<string, string>();
                    dic2.Add("IMEI", phoneNumber);
                    dic2.Add("CMD", "8300");
                    dic2.Add("PARAM1", "1");
                    dic2.Add("PARAM2", "AT+JTT?0013,36.134.79.195,0018,8030");
                    keyValues2.Add(dic2);
                    new SendMsgServer().SendMessage(keyValues2);


                    List<Dictionary<string, string>> keyValues3 = new List<Dictionary<string, string>>();
                    Dictionary<string, string> dic3 = new Dictionary<string, string>();
                    dic3.Add("IMEI", phoneNumber);
                    dic3.Add("CMD", "8300");
                    dic3.Add("PARAM1", "1");
                    dic3.Add("PARAM2", "AT+ECFG_SRVIP=36.134.79.195,8030");
                    keyValues3.Add(dic3);
                    new SendMsgServer().SendMessage(keyValues3);

                    LogHelp.WriteeLog("DownSendUpdateIP", "IP:" + ip + ",PORT:" + port + "===========");
                }
            }
        }

        private static void Handle0F01Data(HandleData808 data)
        {
            double electricityQuantity = Math.Ceiling(data.body[0] / 20.0);

            string updateStr = "UPDATE  `dev_gps_realtime` SET  `online_status` = 1,`voltage_level` = " + electricityQuantity + ",`update_time` = now(),data_time=now() WHERE `device_id` = " + data.deviceInfo.deviceId + ";";
            string result = DBHelp.DBHelp.ExecSql(updateStr);
            if (result == "0")
            {
                string insertSql = $"insert into dev_gps_realtime (device_id,device_phone_num,create_time,online_status,voltage_level,update_time)values({data.deviceInfo.deviceId},'{data.deviceInfo.deviceNo}',now(),1,{electricityQuantity},now());";
                DBHelp.DBHelp.ExecSql(insertSql);
            }
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(data.msgId, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.deviceNo = data.phoneNumber;
            sd.Client = data.client;
            PushSend(sd);

        }



        private static void Handle1206Data(HandleData808 data)
        {
            int serialNumber = GwUtil.ToInt16(data.body, 0);
            int result = data.body[2];//0:成功，1:失败
        }
        private static void Handle1205Data(HandleData808 data)
        {

            string dataStr = "";
            string key = "1205" + data.phoneNumber + data.totalPacket;
            if (data.subPackage)
            {
                lock (rec0104SubMsgDic)
                {
                    if (rec0104SubMsgDic.ContainsKey(key))
                    {
                        Dictionary<int, HandleData808> dic = rec0104SubMsgDic[key];
                        if (dic.ContainsKey(data.curPacket))
                        {
                            dic[data.curPacket] = data;
                        }
                        else
                        {
                            dic.Add(data.curPacket, data);
                        }


                        if (dic.Count >= data.totalPacket)
                        {
                            for (int i = 1; i < data.totalPacket + 1; i++)
                            {
                                dataStr += GwUtil.BytesToHex(dic[i].body);
                            }
                        }

                    }
                    else
                    {
                        Dictionary<int, HandleData808> dic = new Dictionary<int, HandleData808>();
                        dic.Add(data.curPacket, data);
                        rec0104SubMsgDic.Add(key, dic);
                    }
                }
            }
            else
            {
                dataStr = GwUtil.BytesToHex(data.body);
            }

            if (dataStr == "")
            {
                return;
            }
            data.body = GwUtil.HexToBytes(dataStr);

            int serialNumber = GwUtil.ToInt16(data.body, 0);
            int resourceCount = GwUtil.ToInt32(data.body, 2);
            string status = "流水号:" + serialNumber + "|";
            status = "音视频资源总数:" + resourceCount + "|";
            for (int i = 0; i < resourceCount; i++)
            {
                int gateway = data.body[6 + i * 28];
                string startTime = GwUtil.BytesToHex(data.body.Skip(6 + 1 + i * 28).Take(6).ToArray());
                string endTime = GwUtil.BytesToHex(data.body.Skip(6 + 7 + i * 28).Take(6).ToArray());
                string alarmFlag = GwUtil.HexToBin(GwUtil.BytesToHex(data.body.Skip(6 + 13 + i * 28).Take(4).ToArray()), 32);
                int resourceType = data.body[6 + 21 + i * 28];

                int streamType = data.body[6 + 22 + i * 28];

                int saveType = data.body[6 + 23 + i * 28];

                long fileSize = GwUtil.byteArr2long(data.body.Skip(6 + 24 + i * 28).Take(4).ToArray());

                status += "逻辑通道号:" + gateway + "|" + "开始时间:" + startTime + "|" + "结束时间:" + endTime + "|" + "报警标志:" + alarmFlag + "|" + "音视频资源类型:" + resourceType + "|" + "码流类型:" + streamType + "|" + "存储器类型:" + saveType + "|" + "文件大小:" + fileSize + "|";
            }

        }
        private static void Handle1005Data(HandleData808 data)
        {
            DateTime startTime = DateTime.ParseExact(GwUtil.BytesToHex(data.body.Skip(0).Take(6).ToArray()), "yyMMddHHmmss", System.Globalization.CultureInfo.InvariantCulture);
            DateTime endTime = DateTime.ParseExact(GwUtil.BytesToHex(data.body.Skip(6).Take(6).ToArray()), "yyMMddHHmmss", System.Globalization.CultureInfo.InvariantCulture);
            int onCar = GwUtil.ToInt16(data.body, 12);
            int offCar = GwUtil.ToInt16(data.body, 14);
            string status = "起始时间" + startTime + "|";
            status += "结束时间" + endTime + "|";
            status += "上车人数" + onCar + "|";
            status += "下车人数" + offCar + "|";
            LogHelp.WriteeLog("Handle1005Data", status);
        }
        private static void Handle1003Data(HandleData808 data)
        {
            //输入音频编码方式
            int terPara = data.body[0];
            string status = "输入音频编码方式" + terPara + "|";
            //输入音频声道数
            int para1 = data.body[1];
            status += "输入音频声道数" + para1 + "|";
            //输入音频采集率
            int para2 = data.body[2];
            status += "输入音频采集率" + para2 + "|";
            //输入音频采样位数
            int para3 = data.body[3];
            status += "输入音频采样位数" + para3 + "|";
            //音频帧长度
            int para4 = GwUtil.ToInt16(data.body, 4);
            status += "音频帧长度" + para4 + "|";
            //是否支持音频输出
            int para5 = data.body[6];
            status += "是否支持音频输出" + para5 + "|";
            //视频编码方式
            int para6 = data.body[7];
            status += "视频编码方式" + para6 + "|";
            //最大音频物理通道数
            int para7 = data.body[8];
            status += "最大音频物理通道数" + para7 + "|";
            //最大视频物理通道数
            int para8 = data.body[9];
            status += "最大视频物理通道数" + para8 + "|";
            LogHelp.WriteeLog("Handle1003Data", status);
        }
        private static void Handle0800Data(HandleData808 hldata)
        {
            try
            {
                //应答
                string msgbody = GwUtil.IntToHex(hldata.seqId, 4) + GwUtil.IntToHex(0x0800, 4) + "00";
                byte[] setBuffers = GwUtil.BuildPackage(0x8001, hldata.phoneNumber, msgbody);

                SourceData sd = new SourceData();
                sd.bs = setBuffers;
                sd.Client = hldata.client;
                sd.deviceNo = hldata.phoneNumber;
                PushSend(sd);



                string MultimediaID = GwUtil.IntToHex(GwUtil.ToInt32(hldata.body, 0), 8);
                string MultimediaType = string.Empty;
                switch (hldata.body[4])
                {
                    case 0: MultimediaType = "0:图像"; break;
                    case 1: MultimediaType = "1:音频"; break;
                    case 2: MultimediaType = "2:视频"; break;
                }
                string MultimediaFormat = string.Empty;
                switch (hldata.body[5])
                {
                    case 0: MultimediaFormat = "0:JPEG"; break;
                    case 1: MultimediaFormat = "1:TIF"; break;
                    case 2: MultimediaFormat = "2:MP3"; break;
                    case 3: MultimediaFormat = "3:WAV"; break;
                    case 4: MultimediaFormat = "4:WMV"; break;
                    default: MultimediaFormat = "其他保留"; break;
                }
                string EventType = string.Empty;
                switch (hldata.body[6])
                {
                    case 0: EventType = "0:平台下发指令"; break;
                    case 1: EventType = "1:定时动作"; break;
                    case 2: EventType = "2:抢劫报警触发"; break;
                    case 3: EventType = "3:碰撞侧翻报警触发"; break;
                    default: EventType = "其他保留"; break;
                }
                string Ch = hldata.body[7].ToString();

                string content = "多媒体ID: {0}|多媒体类型: {1}|多媒体格式: {2}|事件项编码: {3}|通道ID: {4}";
                content = string.Format(content, MultimediaID, MultimediaType, MultimediaFormat, EventType, Ch);
                LogHelp.WriteeLog("多媒体事件信息上传", hldata.phoneNumber + content);
                //string SqlStr = "insert into " + Global.HisDataBaseName + DateTime.Now.ToString("yyyy_MM_dd")
                //    + ".dbo.UploadTable (PhoneNum,TypeID,TypeName,Data,UpLoadTime) values ("
                //    + QuotedStr(hldata.phoneNumber) + "," + QuotedStr("0800") + "," + QuotedStr("多媒体事件信息上传")
                //    + "," + QuotedStr(content) + ", GetDate())";
                //WcfTool.InsertToDB(SqlStr);
            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("Handle0800Data", e.ToString());
            }
        }


        private static void Handle0705Data(HandleData808 data)
        {
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(0x0705, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int canAllCount = GwUtil.ToInt16(data.body, 0);
            string recTime = GwUtil.BytesToHex(data.body.Skip(2).Take(5).ToArray());

            string recData = "";
            for (int i = 0; i < canAllCount; i++)
            {
                byte[] canIdBs = data.body.Skip(8 + 12 * i).Take(12).ToArray();
                string dataID = GwUtil.HexToBin(GwUtil.BytesToHex(canIdBs.Skip(0).Take(4).ToArray()));

                string canGateNum = dataID[0] == 0 ? "CAN1" : "CAN2";
                string zhenType = dataID[1] == 0 ? "标准帧" : "扩展帧";
                string cjfs = dataID[2] == 0 ? "原始数据" : "采集区间的平均值";
                recData += "CAN_ID:CAN通道号：" + canGateNum + "帧类型：" + zhenType + "采集方式：" + cjfs + "CAN总线ID:" + GwUtil.BinToInt(dataID.Substring(3));

                byte[] canDataBs = canIdBs.Skip(4).Take(8).ToArray();
                recData += "CAN数据：" + GwUtil.BytesToHex(canDataBs);
            }
            LogHelp.WriteeLog("Handle0705Data", data.phoneNumber + recData);

        }

        /// <summary>
        /// 0704 新北斗盲点补传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0704Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x0704, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int Count = GwUtil.ToInt16(body, 0);//数据项个数
            var locType = (byte)body[2];//位置数据类型 0:正常位置批量汇报，2:盲区补报
            List<Gps> ltGps = new List<Gps>();
            int startIndex = 3;
            for (int i = 0; i < Count; i++)
            {
                try
                {
                    int len = GwUtil.ToInt16(body, startIndex);
                    byte[] bs = new byte[len];
                    if (body.Length < startIndex + 2 + len) break;
                    Buffer.BlockCopy(body, startIndex + 2, bs, 0, len);

                    data.body = bs;
                    PositionUpLoadCache(data);

                    startIndex += len + 2;

                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("0704异常：", ex.StackTrace + "\r\n" +
                         "设备号:" + phoneNumber + "原始数据:" + GwUtil.BytesToHex(data.allbs));
                }
            }





        }

        /// <summary>
        /// 0700 行驶记录数据上传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0700Data(HandleData808 data)
        {
            string strData = "";

            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;

            string Data = GwUtil.BytesToHex(body);
            string lsh = Data.Substring(0, 4);
            string CMD = Data.Substring(4, 2);
            Data = Data.Substring(6);

            strData = AnalysisDrivingRecordData(CMD, phoneNumber, Data);



        }

        /// <summary>
        /// 分析行驶记录数据
        /// </summary>
        /// <param name="CMD"></param>
        /// <param name="id"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        private static string AnalysisDrivingRecordData(string CMD, string id, string Data)
        {
            string str = string.Empty;
            switch (CMD)
            {
                case "00"://采集记录仪执行标准版本
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                        str = "采集记录仪执行标准版本:执行标准年号后2位:" + Data.Substring(0, 2) + " 修改单号:" + Data.Substring(2, 2);
                    }
                    break;
                case "01":
                    //采集驾驶员代码及对应的机动车驾驶证号码

                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    string DriverCode = GwUtil.HexToInt(Data.Substring(0, 6)).ToString();
                    string DriverLicense = GwUtil.HexToStr(Data.Substring(6));
                    DriverLicense = DriverLicense.Replace("\0", "");
                    str = "驾驶员代码：" + DriverCode + " 驾驶证号码:" + DriverLicense;
                    str += "驾驶员打印完毕!";

                    break;
                case "02":
                    //采集记录仪的实时时钟
                    str = "记录仪的数据包:" + Data;
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    str += "记录仪的实时时间:" + Data;


                    break;
                case "03":

                    str = "里程数据块内容：" + Data;
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    str += "初始里程值：" + (GwUtil.HexToInt(Data.Substring(24, 8)) * 0.1) + "累计里程值：" + (GwUtil.HexToInt(Data.Substring(32, 8)) * 0.1) + " 实时时间:" + Data.Substring(0, 12) + " 安装时间:" + Data.Substring(12, 12);

                    break;
                case "04":
                    //采集记录仪中的车辆特征系数+
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    str = "当前时间:" + Data.Substring(0, 12) + "记录仪脉冲系数：" + GwUtil.HexToInt(Data.Substring(12, 4));

                    break;
                case "05":
                    //采集车辆信息
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    str = "车辆识别代号：" + GwUtil.HexToStr(Data.Substring(0, 17 * 2)) + "车牌号：" + GwUtil.HexToStr(Data.Substring(34, 24)) + "车牌分类:" + GwUtil.HexToStr(Data.Substring(58, 24));

                    break;
                case "06"://采集记录仪状态信号配置信息
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    string reaTime = Data.Substring(0, 12);
                    string ioState = (GwUtil.HexToStr(Data.Substring(12))).Replace("\0", "");

                    str = "实时时间：" + reaTime + " 状态信号配置：" + ioState;

                    break;

                case "07"://采集记录仪唯一性编号
                    if (Data.StartsWith("557A"))
                    {
                        Data = Data.Substring(12, Data.Length - 14);
                    }
                    string authCode = (GwUtil.HexToStr(Data.Substring(0, 14))).Replace("\0", "");
                    string model = (GwUtil.HexToStr(Data.Substring(14, 32))).Replace("\0", "");
                    string manuDate = Data.Substring(46, 6);
                    string lsh = Data.Substring(52, 8);
                    str = ("生产厂CCC认证代码:" + authCode + " 认证产品型号:" + model + "记录仪的生产日期:" + manuDate + "产品生产流水号:" + lsh);

                    break;

                default:
                    str = ("命令字:" + id + "采集数据内容:" + Data);
                    break;
            }

            LogHelp.WriteeLog("AnalysisDrivingRecordData", str);
            return Data;
        }

        /// <summary>
        /// 0802 存储多媒体数据检索应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0802Data(HandleData808 hldata)
        {
            try
            {
                string data = GwUtil.BytesToHex(hldata.body);
                string strReplySerial = data.Substring(0, 4);//应答流水号
                int Count = GwUtil.HexToInt(data.Substring(4, 4));//多媒体数据总项数
                data = data.Substring(8);
                for (int i = 0; i < Count; i++)
                {
                    OneMultiMediaReply(hldata.phoneNumber, strReplySerial, data.Substring(0, 70));
                    data = data.Substring(70);
                }
                LogHelp.WriteeLog("存储多媒体数据检索应答", strReplySerial + Count);
            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("存储多媒体数据检索应答异常：", e.Message);

            }
        }
        /// <summary>
        /// 解析多媒体数据
        /// </summary>
        /// <param name="PhoneNum"></param>
        /// <param name="ReplySerial"></param>
        /// <param name="Data"></param>
        private static void OneMultiMediaReply(string PhoneNum, string ReplySerial, string Data)
        {

            int MediaId = GwUtil.HexToInt(Data.Substring(0, 8));

            int MultiMediaType = GwUtil.HexToInt(Data.Substring(8, 2));
            int Ch = GwUtil.HexToInt(Data.Substring(10, 2));
            int EventType = GwUtil.HexToInt(Data.Substring(12, 2));
            Data = Data.Substring(14);
            Gps GData = GpsTool.HandleGps(GwUtil.HexToBytes(Data));

            LogHelp.WriteeLog("0802多媒体数据：多媒体Id:", MediaId + "多媒体类型：" + MultiMediaType + "通道 ID :" + Ch + "事件:" + EventType);
        }

        /// <summary>
        /// 6005 上报司机退登消息
        /// </summary>
        /// <param name="data"></param>
        private static void Handle6005Data(HandleData808 data)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 0901 数据压缩上传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0901Data(HandleData808 data)
        {

        }

        /// <summary>
        /// 8304 信息服务
        /// </summary>
        /// <param name="data"></param>
        private static void Handle8304Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x8304, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);
        }

        /// <summary>
        /// 0303 信息点播
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0303Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x0303, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int InfoType = body[0];
            int InfoFlag = body[1];
            LogHelp.WriteeLog("信息类型：", InfoType + " 点播/取消标志:" + InfoFlag + ",phonenum=" + phoneNumber);

        }

        /// <summary>
        /// 0302 提问应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0302Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x0302, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int AnswerSerialNumber = GwUtil.ToInt16(body, 0);
            int Answer = body[2];
            LogHelp.WriteeLog("提问应答   流水号：", AnswerSerialNumber + " 答案ID:" + Answer + ",phonenum=" + phoneNumber);


        }

        /// <summary>
        /// 0301 事件报告
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0301Data(HandleData808 data)
        {
            //应答
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(0x0301, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            string EventID = data.body[0].ToString();
            LogHelp.WriteeLog("事件报告   事件ID：", EventID + ",phonenum=" + data.phoneNumber);

        }

        /// <summary>
        /// 0900 数据上行透传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0900Data(HandleData808 hldata)
        {
            try
            {
                //应答
                string msgbody = GwUtil.IntToHex(hldata.seqId, 4) + GwUtil.IntToHex(0x0900, 4) + "00";
                byte[] setBuffers = GwUtil.BuildPackage(0x8001, hldata.phoneNumber, msgbody);

                SourceData sd = new SourceData();
                sd.bs = setBuffers;
                sd.Client = hldata.client;
                sd.deviceNo = hldata.phoneNumber;
                PushSend(sd);


                LogHelp.WriteeLog("数据上行透传应答消息：", hldata.phoneNumber + "  " + GwUtil.BytesToHex(setBuffers));

                int TransparentType = hldata.body[0];
                if (TransparentType == 0x00)//GNSS模块详细定位数据
                {

                    return;
                }
                else if (TransparentType == 0x0B)//道路运输证IC卡信息
                {

                }
                else if (TransparentType == 0x41)//串口1透传消息
                {

                }
                else if (TransparentType == 0x42)//串口2透传消息
                {

                }


            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("数据上行透传：", e.Message);

            }
        }


        /// <summary>
        /// 0701 电子运单上报
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0701Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x0701, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int len = GwUtil.ToInt32(body, 0);
            byte[] bs = new byte[body.Length - 4];
            Buffer.BlockCopy(body, 4, bs, 0, bs.Length);
            string Status = GwUtil.HexToStr(GwUtil.BytesToHex(bs));
            LogHelp.WriteeLog("电子运单长度：", len + "  电子运单内容：" + Status + ",phonenum=" + phoneNumber);




            DevInfo dev = redis.HashGet<DevInfo>("allCarsCache", phoneNumber.TrimStart('0'));


            string SqlStr = "insert into lbs_car_upload_data (sim_card,msg_id,msg_name,data,create_date,vehicle_no,vehicle_color) values ('"
                + phoneNumber + "','0701','电子运单上报','" + Status + "', now(),'" + dev.licnum + "'," + dev.plateColor + ");";
            AddToUpdateSqlList(SqlStr);
        }

        /// <summary>
        /// 0702 驾驶员身份信息采集上报
        /// </summary>
        /// <param name="scdata"></param>
        private static void Handle0702Data(HandleData808 scdata)
        {
            string phoneNumber = scdata.phoneNumber;
            int seqId = scdata.seqId;
            int encry = scdata.encry;
            bool subPackage = scdata.subPackage;
            bool multiMedia = scdata.multiMedia;
            int bodyLength = scdata.bodyLength;
            ushort totalPacket = scdata.totalPacket;
            ushort curPacket = scdata.curPacket;
            byte[] body = scdata.body;


            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x0702, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = scdata.client;
            sd.deviceNo = scdata.phoneNumber;
            PushSend(sd);

            //2013-808
            int status = body[0];//1:插卡，2：拔卡
            string time = GwUtil.BytesToHex(body.Skip(1).Take(6).ToArray());

            //驾驶员姓名
            string DriverName = "";
            //从业资格证编码
            string QualificationCertificate = "";
            //发证机构名称
            string LicenceIssuingAuthority = "";
            //证件有效期
            string LicenceTime = "";
            string Status = ((status == 1) ? "插卡" : "拔卡") + "时间:" + time;
            if (GwUtil.IsDate(time))
            {
                if (status == 1)
                {
                    int result = body[7];//0:读卡成功，1-4：读卡失败
                    Status += (result == 0) ? "读卡成功" : "读卡失败";
                    if (result == 0)
                    {
                        int nameLen = body[8];
                        DriverName = GwUtil.Bytes2String(body, 9, nameLen);
                        Status += "驾驶员姓名：" + DriverName;
                        Status += "驾驶员身份证编码：" + QualificationCertificate;

                        QualificationCertificate = GwUtil.Bytes2String(body, 9 + nameLen, 20).Replace("\0", "");
                        Status += "从业资格证编码：" + QualificationCertificate;

                        int m = body[29 + nameLen];
                        LicenceIssuingAuthority = GwUtil.Bytes2String(body, 30 + nameLen, m).Replace("\0", "");
                        Status += "发证机关名称：" + LicenceIssuingAuthority;

                        LicenceTime = GwUtil.BytesToHex(body.Skip(30 + nameLen + m).Take(4).ToArray());
                        Status += "证件有效期：" + LicenceTime;

                        DevInfo dev = redis.HashGet<DevInfo>("allCarsCache", phoneNumber.TrimStart('0'));


                        //      string SqlStr = "insert into lbs_car_upload_data (sim_card,msg_id,msg_name,data,create_date,vehicle_no,vehicle_color) values ('"
                        //+ phoneNumber + "','0702','驾驶员身份信息采集','" + Status + "', now(),'" + dev.licnum + "'," + dev.plateColor + ");";
                        //      AddToUpdateSqlList(SqlStr);
                    }
                }
            }
            else
            {
                //2011-808
                string data = GwUtil.BytesToHex(body);
                int Len = GwUtil.HexToInt(data.Substring(0, 2));
                DriverName = GwUtil.HexToStr(data.Substring(2, Len * 2));
                DriverName = DriverName.Replace("\0", "");
                Status += "驾驶员姓名：" + DriverName + "|";
                string IdentityCardNumber = GwUtil.HexToStr(data.Substring(2 + Len * 2, 40));
                IdentityCardNumber = IdentityCardNumber.Replace("\0", "");
                Status = Status + "驾驶员身份证编码：" + IdentityCardNumber + "|";
                QualificationCertificate = GwUtil.HexToStr(data.Substring(2 + Len * 2 + 40, 80));
                QualificationCertificate = QualificationCertificate.Replace("\0", "");
                Status = Status + "从业资格证编码：" + QualificationCertificate + "|";
                int n = 2 + Len * 2 + 40 + 80;
                Len = GwUtil.HexToInt(data.Substring(n, 2));
                LicenceIssuingAuthority = GwUtil.HexToStr(data.Substring(n + 2, Len * 2));
                LicenceIssuingAuthority = LicenceIssuingAuthority.Replace("\0", "");
                Status = Status + "发证机关名称：" + LicenceIssuingAuthority;
            }
            //string update8103 = $"update lbs_send_down set response='{Status}',response_time=now(),send_status=1 where send_id in (select max_id from (select max(send_id) as max_id from lbs_send_down where sim='{phoneNumber}'and response is null and command_type='8702') as a );";
            //AddToUpdateSqlList(update8103);
            LogHelp.WriteeLog("", Status);
        }

        /// <summary>
        /// 0104 查询终端参数应答
        /// </summary>
        /// <param name="scdata"></param>
        private static void Handle0104Data(HandleData808 scdata)
        {
            //应答
            string msgbody = GwUtil.IntToHex(scdata.seqId, 4) + GwUtil.IntToHex(0x0104, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, scdata.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = scdata.client;
            sd.deviceNo = scdata.phoneNumber;
            PushSend(sd);

            if (scdata.body.Length < 9)
            {
                return;
            }



            string data = "";
            string key = "0104" + scdata.phoneNumber + scdata.totalPacket;
            if (scdata.subPackage)
            {
                lock (rec0104SubMsgDic)
                {
                    if (rec0104SubMsgDic.ContainsKey(key))
                    {
                        Dictionary<int, HandleData808> dic = rec0104SubMsgDic[key];
                        if (dic.ContainsKey(scdata.curPacket))
                        {
                            dic[scdata.curPacket] = scdata;
                        }
                        else
                        {
                            dic.Add(scdata.curPacket, scdata);
                        }
                        if (dic.Count >= scdata.totalPacket)
                        {
                            for (int i = 1; i < scdata.totalPacket + 1; i++)
                            {
                                data += GwUtil.BytesToHex(dic[i].body);
                            }
                        }

                    }
                    else
                    {
                        Dictionary<int, HandleData808> dic = new Dictionary<int, HandleData808>();
                        dic.Add(scdata.curPacket, scdata);
                        rec0104SubMsgDic.Add(key, dic);
                    }
                }
            }
            else
            {
                data = GwUtil.BytesToHex(scdata.body);
            }
            #region 808解析
            if (data == "")
            {
                return;
            }
            //string data = GwUtil.BytesToHex(scdata.body);

            string SerialNumber = data.Substring(0, 4);
            int ParaCount = GwUtil.HexToInt(data.Substring(4, 2));

            data = data.Substring(6);
            string CMD = string.Empty;
            int Len = 0;
            string Value = string.Empty;
            string Status = string.Empty;
            while (data.Length > 0)
            {
                CMD = data.Substring(0, 8);
                CMD = CMD.Substring(4);
                Len = GwUtil.HexToInt(data.Substring(8, 2));
                if (Len * 2 > data.Length)
                {
                    break;
                }
                Value = data.Substring(10, Len * 2);
                switch (CMD)
                {
                    #region 子命令
                    case "0001":
                        //设置终端心跳发送间隔，单位为(s)
                        Status = Status + "终端心跳发送间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0002":
                        //TCP消息应答超时时间，单位为(s)
                        Status = Status + "TCP消息应答超时时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0003":
                        //TCP消息重传次数
                        Status = Status + "TCP消息重传次数" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0004":
                        //UDP消息应答超时时间，单位为秒(s)
                        Status = Status + "UDP消息应答超时时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0005":
                        //UDP消息重传次数
                        Status = Status + "UDP消息重传次数" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0006":
                        //SMS消息应答超时时间，单位为秒(s)
                        Status = Status + "SMS消息应答超时时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0007":
                        //SMS消息重传次数
                        Status = Status + "SMS消息重传次数" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0010":
                        //主服务器APN，无线通信拨号访问点。若网络制式为CDMA,则该处为PPP拨号号码
                        Status = Status + "主服务器APN" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0011":
                        //主服务器无线通信拨号用户名
                        Status = Status + "主服务器无线通信拨号用户名" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0012":
                        //主服务器无线通信拨号密码
                        Status = Status + "主服务器无线通信拨号密码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0013":
                        //主服务器地址，IP或域名
                        Status = Status + "主服务器地址" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0014":
                        //备份服务器APN,无线通信拨号访问点
                        Status = Status + "备份服务器APN" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0015":
                        //备份服务器无线通信拨号用户名
                        Status = Status + "备份服务器无线通信拨号用户名" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0016":
                        //备份服务器无线通信拨号密码
                        Status = Status + "备份服务器无线通信拨号密码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0017":
                        //备份服务器地址，IP或域名
                        Status = Status + "备份服务器地址" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0018":
                        //服务器TCP端口
                        Status = Status + "服务器TCP端口" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0019":
                        //服务器UDP端口
                        Status = Status + "服务器UDP端口" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;

                    case "001A":
                        //道路运输证IC卡认证主服务器IP地址或域名
                        Status = Status + "道路运输证IC卡认证主服务器IP地址或域名" + GwUtil.HexToStr(Value).ToString() + "|";
                        break;
                    case "001B":
                        //道路运输证IC卡认证主服务器TCP端口
                        Status = Status + "道路运输证IC卡认证主服务器TCP端口" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "001C":
                        //道路运输证IC卡认证主服务器UDP端口
                        Status = Status + "道路运输证IC卡认证主服务器UDP端口" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "001D":
                        //道路运输证IC卡认证备份服务器IP地址或域名，端口同主服务器
                        Status = Status + "道路运输证IC卡认证主服务器IP地址或域名" + GwUtil.HexToStr(Value).ToString() + "|";
                        break;
                    case "0020":
                        //位置汇报策略，0：定时汇报；1：定距汇报；2：定时和定距汇报
                        if (GwUtil.HexToInt(Value) == 0)
                            Status = Status + "位置汇报策略--定时汇报|";
                        else if (GwUtil.HexToInt(Value) == 1)
                            Status = Status + "位置汇报策略--定距汇报|";
                        else if (GwUtil.HexToInt(Value) == 2)
                            Status = Status + "位置汇报策略--定时和定距汇报|";
                        break;
                    case "0021":
                        //位置汇报方案，0：根据ACC状态；1：根据登录状态和ACC状态，先判断登录状态，若登录再根据ACC状态
                        if (GwUtil.HexToInt(Value) == 0)
                            Status = Status + "位置汇报方案--根据ACC状态|";
                        else if (GwUtil.HexToInt(Value) == 1)
                            Status = Status + "位置汇报方案--根据登录状态和ACC状态|";
                        break;
                    case "0022":
                        //驾驶员未登录汇报时间间隔，单位为秒（s）, > 0
                        Status = Status + "驾驶员未登录汇报时间间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;


                    case "0027":
                        //休眠时汇报时间间隔，单位为秒(s), > 0
                        Status = Status + "休眠时汇报时间间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0028":
                        //紧急报警时汇报时间间隔单位为秒(s), > 0
                        Status = Status + "紧急报警时汇报时间间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0029":
                        //缺省时间汇报间隔，单位为秒(s), > 0
                        Status = Status + "缺省时间汇报间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;


                    case "002C":
                        //缺省距离汇报间隔，单位为米(m), > 0
                        Status = Status + "缺省距离汇报间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "002D":
                        //驾驶员未登录汇报距离间隔，单位为米（m）, > 0
                        Status = Status + "驾驶员未登录汇报距离间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "002E":
                        //休眠时汇报距离间隔，单位为米(m), > 0
                        Status = Status + "休眠时汇报距离间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "002F":
                        //紧急报警时汇报距离间隔，单位为米（m）, > 0
                        Status = Status + "紧急报警时汇报距离间隔" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0030":
                        //拐点补传角度， < 180
                        Status = Status + "拐点补传角度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0031": //电子围栏半径
                        Status = Status + "电子围栏半径" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;



                    case "0040":
                        //监控平台电话号码
                        Status = Status + "监控平台电话号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0041":
                        //复位电话号码，可采用此电话号码拨打终端电话让终端复位
                        Status = Status + "复位电话号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0042":
                        //恢复出厂设置电话号码，可采用此电话号码拨打终端电话让终端恢复出厂设置
                        Status = Status + "恢复出厂设置电话号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0043":
                        //监控平台SMS电话号码
                        Status = Status + "监控平台SMS电话号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0044":
                        //接收终端SMS文本报警号码
                        Status = Status + "接收终端SMS文本报警号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0045":
                        //终端接听电话策略，0：自动接听；1：ACC ON时自动接听，OFF时手动接听
                        if (GwUtil.HexToInt(Value) == 0)
                            Status = Status + "终端接听电话策略-自动接听|";
                        else if (GwUtil.HexToInt(Value) == 1)
                            Status = Status + "终端接听电话策略-ACC ON时自动接听，OFF时手动接听|";
                        break;
                    case "0046":
                        //每次最长通话时间，单位为秒（s），0为不允许通话，0xFFFFFFFF为不限制
                        Status = Status + "每次最长通话时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0047":
                        //当月最长通话时间，单位为秒（s），0为不允许通话，0xFFFFFFFF为不限制
                        Status = Status + "当月最长通话时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0048":
                        //监听电话号码
                        Status = Status + "监听电话号码" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0049":
                        //监管平台特权短信号码
                        Status = Status + "监管平台特权短信号码" + GwUtil.HexToStr(Value) + "|";
                        break;


                    case "0050":
                        //报警屏蔽字，与位置信息汇报消息中的报警标志相对应，相应位为1则相应报警被屏蔽
                        Status = Status + "报警屏蔽字" + GwUtil.HexToBin(Value, 32) + "|";
                        break;
                    case "0051":
                        //报警发送文本SMS开关，与位置信息汇报消息中的报警标志相对应，相应为1则相应报警时发送文本SMS
                        Status = Status + "报警发送文本SMS开关" + GwUtil.HexToBin(Value, 32) + "|";
                        break;
                    case "0052":
                        //报警拍摄开关，与位置信息汇报消息中的报警标志相对应，相应位为1则相应报警时摄像头拍摄，默认 第1路拍照
                        Status = Status + "报警拍摄开关" + GwUtil.HexToBin(Value, 32) + "|";
                        break;
                    case "0053":
                        //报警拍摄存储标志，与位置信息汇报消息中的报警标志相对应，相应位为1则对相应报警时拍的照片进行存储，否则实时上传
                        Status = Status + "报警拍摄存储标志" + GwUtil.HexToBin(Value, 32) + "|";
                        break;
                    case "0054":
                        //关键标志，与位置信息汇报消息中的报警标志相对应，相应位为1则对应报警为关键报警
                        Status = Status + "关键标志" + GwUtil.HexToBin(Value, 32) + "|";
                        break;
                    case "0055":
                        //最高速度，单位为千米每小时（km/h）
                        Status = Status + "最高速度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0056":
                        //超速持续时间，单位为秒（s）
                        Status = Status + "超速持续时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0057":
                        //连续驾驶时间门限，单位为秒（s）
                        Status = Status + "连续驾驶时间门限" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0058":
                        //当天累计驾驶时间门限，单位为秒（s）
                        Status = Status + "当天累计驾驶时间门限" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0059":
                        //最小休息时间，单位为秒（s）
                        Status = Status + "最小休息时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "005A":
                        //最长停车时间，单位为秒（s）
                        Status = Status + "最长停车时间" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "005B":
                        //超速报警预警差值，单位为1/10km/h
                        Status = Status + "超速报警预警差值" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "005C":
                        //疲劳驾驶预警差值，单位为秒（s）,>0
                        Status = Status + "疲劳驾驶预警差值" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "005D":
                        //碰撞报警参数设置：b7-b0:碰撞时间，单位4ms；b15-b8:碰撞加速度，单位0.1g，设置范围在：0-79之间，默认为10
                        Status = Status + "碰撞加速度" + GwUtil.HexToInt(Value.Substring(0, 2)).ToString() + "|";
                        Status = Status + "碰撞时间" + GwUtil.HexToInt(Value.Substring(2, 2)).ToString() + "|";
                        break;
                    case "005E":
                        //侧翻报警参数设置：侧翻角度，单位1度，默认为30度
                        Status = Status + "疲劳驾驶预警差值" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0064":
                        //定时拍照控制
                        Status = Status + "定时拍照控制" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0065":
                        //定距拍照控制
                        Status = Status + "定距拍照控制" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;

                    case "0070":
                        //图像/视频质量，1~10， 1最好
                        Status = Status + "图像/视频质量" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0071":
                        //亮度，0~255
                        Status = Status + "亮度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0072":
                        //对比度，0~127
                        Status = Status + "对比度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0073":
                        //饱和度，0~127
                        Status = Status + "饱和度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0074":
                        //色度，0~255
                        Status = Status + "色度" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0075":
                        //音视频参数设置
                        Status = Status + "音视频参数设置" + Value + "|";
                        break;

                    case "0076":
                        //音视频通道列表设置,音视频物理与逻辑通道对照表
                        Status = Status + "音视频通道列表设置" + Value + "|";
                        break;
                    case "0077":
                        //单独视频通道参数设置，根据逻辑通道号设置 19长度
                        Status = Status + "单独视频通道参数设置" + Value + "|";
                        break;
                    case "0079":
                        //特殊报警录像参数设置 3
                        Status = Status + "特殊报警录像参数设置" + Value + "|";
                        break;
                    case "007A":
                        //视频相关报警屏蔽字, 屏蔽对应设置标识位
                        Status = Status + "视频相关报警屏蔽字" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "007B":
                        //图像分析报警参数设置
                        Status = Status + "图像分析报警参数设置" + Value + "|";
                        break;
                    case "007C":
                        //终端休眠唤醒模式设置
                        Status = Status + "终端休眠唤醒模式设置" + Value + "|";
                        break;

                    case "0080":
                        //车辆里程表读数，1/10km
                        Status = Status + "车辆里程表读数" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0081":
                        //车辆所在的省域ID，1~255
                        Status = Status + "车辆所在的省域ID" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0082":
                        //车辆所在的市域ID，1~255
                        Status = Status + "车辆所在的市域ID" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0083":
                        //公安交通管理部门颁发的机动车号牌
                        Status = Status + "机动车号牌" + GwUtil.HexToStr(Value) + "|";
                        break;
                    case "0084":
                        //车牌颜色，按照JT/T415--2006中5.4.12的规定
                        Status = Status + "车牌颜色" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;

                    case "0090":
                        //GNSS定位模式
                        Status = Status + "GNSS定位模式" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0091":
                        //GNSS波特率
                        Status = Status + "GNSS波特率" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0092":
                        //GNSS模块详细定位数据输出频率
                        Status = Status + "GNSS模块详细定位数据输出频率" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0093":
                        //GNSS模块详细定位数据采集频率，单位为秒
                        Status = Status + "GNSS模块详细定位数据采集频率" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0094":
                        //GNSS模块详细定位数据上传方式
                        Status = Status + "GNSS模块详细定位数据上传方式" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0095":
                        //GNSS模块详细定位数据上传设置
                        Status = Status + "GNSS模块详细定位数据上传设置" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0100":
                        //CAN总线通道1采集时间间隔ms
                        Status = Status + "CAN总线通道1采集时间间隔ms" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0101":
                        //CAN总线通道1上传时间间隔s
                        Status = Status + "CAN总线通道1上传时间间隔s" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0102":
                        //CAN总线通道1上传时间间隔s
                        Status = Status + "CAN总线通道2采集时间间隔s" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0103":
                        //CAN总线通道1上传时间间隔s
                        Status = Status + "CAN总线通道2上传时间间隔s" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    case "0110":
                        //CAN总线ID单独采集设置
                        Status = Status + "CAN总线ID单独采集设置" + GwUtil.HexToInt(Value).ToString() + "|";
                        break;
                    default:
                        Status = Status + CMD + Value + "|";
                        break;
                        #endregion
                }
                data = data.Substring(10 + Len * 2);
            }
            //更新下发设备表
            string key1 = scdata.phoneNumber + "8104" + SerialNumber;
            lock (downSendMsgDic)
            {
                if (downSendMsgDic.ContainsKey(key1))
                {
                    string updateSql = $"update lbs_send_down set response='{Status}',response_time=now(),send_status=1  where send_id ={downSendMsgDic[key1]};";
                    AddToUpdateSqlList(updateSql);
                    downSendMsgDic.Remove(key1);
                }
                else if (downSendMsgDic.ContainsKey(scdata.phoneNumber + "8106" + SerialNumber))
                {
                    string updateSql = $"update lbs_send_down set response='{Status}',response_time=now(),send_status=1  where send_id ={downSendMsgDic[scdata.phoneNumber + "8106" + SerialNumber]};";
                    AddToUpdateSqlList(updateSql);
                    downSendMsgDic.Remove(scdata.phoneNumber + "8106" + SerialNumber);
                }
            }
            LogHelp.WriteeLog("", "参数总数：" + ParaCount.ToString() + "  " + Status + ",PhoneNum=" + scdata.phoneNumber);

            #endregion
        }

        /// <summary>
        /// 查询终端属性应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0107Data(HandleData808 data)
        {

            //终端类型
            int terPara = GwUtil.ToInt16(data.body, 0);
            string Status = "终端类型" + terPara + "|";

            //制造商ID
            string ManufacturerId = GwUtil.Bytes2String(data.body, 2, 5);

            Status += "制造商ID" + ManufacturerId + "|";
            //终端型号
            string TerminalType = GwUtil.Bytes2String(data.body, 7, 20).Replace("\0", "");
            Status += "终端型号" + TerminalType + "|";

            //终端ID
            string TerminalId = GwUtil.Bytes2String(data.body, 27, 7).Replace("\0", "");
            Status += "终端ID" + TerminalId + "|";

            //终端sim卡ICCID
            string TerICCID = GwUtil.BytesToHex(data.body.Skip(34).Take(10).ToArray());
            Status += "终端sim卡ICCID" + TerICCID + "|";

            //终端硬件版本号
            int n = data.body[44];
            string TerminalHardwareVersion = GwUtil.Bytes2String(data.body, 45, n);
            Status += "终端硬件版本号" + TerminalHardwareVersion + "|";

            int m = data.body[45 + n];
            //终端固件版本号
            string TerminalFirmwareVersion = GwUtil.Bytes2String(data.body, 46 + n, m);
            Status += "终端固件版本号" + TerminalFirmwareVersion + "|";

            //GNSS模块属性
            int gnssPara = data.body[46 + n + m];
            Status += "GNSS模块属性" + gnssPara + "|";

            //通信模块属性
            int comModuleAttri = data.body[46 + n + m];
            Status += "通信模块属性" + comModuleAttri;

            LogHelp.WriteeLog("", "查询终端属性应答:" + Status);
            string update8103 = $"update lbs_send_down set response='{Status}',response_time=now(),send_status=1  where send_id in (select max_id from (select max(send_id) as max_id from lbs_send_down where sim='{data.phoneNumber}' and command_type='8107') as a );";
            AddToUpdateSqlList(update8103);

        }
        /// <summary>
        /// 终端升级结果通知
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0108Data(HandleData808 data)
        {
            //升级类型
            int upgradeType = data.body[0];//0：终端，12：道路运输证IC卡读卡器，52：北斗卫星定位模块
            //升级结果
            int upgradeResults = data.body[1];//0：成功 1：失败 2：取消
        }



        /// <summary>
        /// 0805 终端拍照应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0805Data(HandleData808 data)
        {
            int n808Serial = GwUtil.ToInt16(data.body, 0);
            byte result = data.body[2];











            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(0x0805, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);
        }

        /// <summary>
        /// 0801 多媒体数据上传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0801Data(HandleData808 hldata)
        {
            try
            {

                LogHelp.WriteeLog("", "多媒体数据上传 总包数：" + hldata.totalPacket.ToString() + "  当前包：" + hldata.curPacket.ToString());

                Multimedia media;
                string bs = hldata.phoneNumber + "-" + hldata.totalPacket.ToString();
                lock (MultiMediaList)
                {
                    if (MultiMediaList.ContainsKey(bs))
                        media = (Multimedia)MultiMediaList[bs];
                    else
                    {
                        media = new Multimedia(hldata.phoneNumber, hldata.totalPacket, hldata.curPacket, string.Format("{0:yyyyMMddHHmmss}", System.DateTime.Now));
                        MultiMediaList.Add(bs, media);
                    }
                }

                if (hldata.curPacket == 1)
                {

                    media.MultiMediaID = GwUtil.IntToHex(GwUtil.ToInt32(hldata.body, 0), 8);
                    media.MultiMediaType = hldata.body[4];
                    media.MultiMediaFormat = hldata.body[5];
                    media.MultiMediaEvent = hldata.body[6];
                    media.ChannelID = hldata.body[7];
                    media.DeviceID = hldata.phoneNumber;
                    media.TotalPacket = hldata.totalPacket;
                    string hex = GwUtil.BytesToHex(hldata.body);
                    string FirstData = hex.Substring(16);

                    //2013-12-17
                    string strLoc = FirstData.Substring(0, 56);
                    media.StrLoc = strLoc;

                    if (media.MultiMediaType == 0)
                        FirstData = FirstData.Substring(FirstData.IndexOf("FFD8"));
                    else if (media.MultiMediaType == 2)
                        FirstData = FirstData.Substring(FirstData.IndexOf("5249"));

                    string msgbody = GwUtil.IntToHex(hldata.seqId, 4) + GwUtil.IntToHex(0x0801, 4) + "00";
                    byte[] setBuffers = GwUtil.BuildPackage(0x8001, hldata.phoneNumber, msgbody);
                    SourceData sd = new SourceData();
                    sd.bs = setBuffers;
                    sd.Client = hldata.client;
                    sd.deviceNo = hldata.phoneNumber;
                    PushSend(sd);
                    //        ShowDebug("发送时间[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + head.PhoneNum.Substring(1) +
                    //"\r\n" + FGInfo(sd));

                    media.AddImageData(hldata.curPacket, FirstData);
                }
                else //不是首包
                {
                    media.DeviceID = hldata.phoneNumber;
                    media.TotalPacket = hldata.totalPacket;
                    media.AddImageData(hldata.curPacket, GwUtil.BytesToHex(hldata.body));

                    string msgbody = GwUtil.IntToHex(hldata.seqId, 4) + GwUtil.IntToHex(0x0801, 4) + "00";
                    byte[] setBuffers = GwUtil.BuildPackage(0x8001, hldata.phoneNumber, msgbody);
                    SourceData sd = new SourceData();
                    sd.bs = setBuffers;
                    sd.Client = hldata.client;
                    sd.deviceNo = hldata.phoneNumber;
                    PushSend(sd);
                    /*
                     * 多媒体上传时，当上传最后一个数据包时不要给通用应答，直接回复8800.我们平台多给了一个通用应答。
                     */
                }
                if (media.GetReceiveOver())//
                {
                    string msgbody = media.MultiMediaID + "00";

                    byte[] setBuffers = GwUtil.BuildPackage(0x8800, hldata.phoneNumber, msgbody);

                    SourceData sd = new SourceData();
                    sd.bs = setBuffers;
                    sd.Client = hldata.client;
                    sd.deviceNo = hldata.phoneNumber;
                    PushSend(sd);
                    SaveMediaToFile(ImageSavePath, media, hldata.phoneNumber);
                }
                //if (media.GetReceiveOver() /*|| CurBack == TotalBack*/)
                //{
                //    if (media.ErrCode == "")
                //    {
                //        string msgbody = media.MultiMediaID + "00";
                //        byte[] setBuffers = GwUtil.BuildPackage(0x8800, hldata.phoneNumber, msgbody);
                //        SourceData sd = new SourceData();
                //        sd.bs = setBuffers;
                //        sd.Client = hldata.client;
                //        PushSend(sd);

                //        WriteeLog("多媒体回复：" + GwUtil.BytesToHex(setBuffers));

                //        //保存多媒体数据
                //        SaveMediaToFile(ImageSavePath, media, hldata.phoneNumber);
                //    }
                //    else
                //    {
                //        string msgbody = media.MultiMediaID + GwUtil.IntToHex(media.ErrCode.Length / 4, 2) + media.ErrCode;
                //        byte[] setBuffers = GwUtil.BuildPackage(0x8800, hldata.phoneNumber, msgbody);

                //        SourceData sd = new SourceData();
                //        sd.bs = setBuffers;
                //        sd.Client = hldata.client;
                //        PushSend(sd);
                //    }
                //}
                //else
                //{
                //    WriteeLog("没收完：" + hldata.curPacket);
                //}

            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("", "多媒体数据上传处理失败：" + e.Message);
            }
        }
        private static void SaveMediaToFile(string PhotoPath, Multimedia media, string PhoneNum)
        {
            //string[] rets;
            //byte[] gnss_data = null;
            try
            {
                string v_path = string.Format("{0:yyyyMM}", System.DateTime.Now);
                if (!Directory.Exists(ImageSavePath))
                {
                    Directory.CreateDirectory(ImageSavePath);
                }
                string path = ImageSavePath + v_path;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                path = path + "/" + media.DeviceID;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                Gps GData = null;
                string data = media.StrLoc;

                if (data != null && data.Length >= 56)
                {
                    GData = new Gps();
                    GData.PhoneNum = PhoneNum;
                    GData.TheAlarm = GwUtil.GetAlarm(data.Substring(0, 8));
                    GData.TheStatus = GwUtil.GetStatus(data.Substring(8, 8));
                    GData.Latitude = GwUtil.HexToInt(data.Substring(16, 8)) / 1000000.0;
                    GData.Longitude = GwUtil.HexToInt(data.Substring(24, 8)) / 1000000.0;
                    GData.high = GwUtil.HexToInt(data.Substring(32, 4));
                    GData.Speed = (int)(GwUtil.HexToInt(data.Substring(36, 4)) / 10.0);
                    GData.Direction = GwUtil.HexToInt(data.Substring(40, 4));
                    var strTime = "";

                    try
                    {
                        strTime = data.Substring(44, 12);

                        GData.GpsTime = DateTime.ParseExact(strTime, "yyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture);
                        string s = string.Format("多媒体位置信息： 纬度：{0} 经度：{1} 高度：{2} 速度：{3} 方向：{4} 时间：{5:yyyy-MM-dd HH:mm:ss} 终端手机号：{6}",
                            GData.Latitude, GData.Longitude, GData.high, GData.Speed, GData.Direction, GData.GpsTime, PhoneNum);
                        LogHelp.WriteeLog("", s);
                    }
                    catch (System.Exception ex)
                    {
                        LogHelp.WriteeLog("", ex.ToString() + "\r\n, strTime513:" + strTime);
                        GData.GpsTime = DateTime.Now;
                    }

                }

                string kzm = string.Empty;
                switch (media.MultiMediaFormat)
                {
                    case 0:
                        kzm = ".jpeg";
                        break;
                    case 1:
                        kzm = ".tif";
                        break;
                    case 2:
                        kzm = ".mp3";
                        break;
                    case 3:
                        kzm = ".wav";
                        break;
                    case 4:
                        kzm = ".wmv";
                        break;
                }
                string v_filename = path + "/" + media.PhotoTime + "-" + media.ChannelID.ToString() + kzm;
                if (File.Exists(v_filename))
                {
                    lock (MultiMediaList)
                    {
                        MultiMediaList.Remove(media.DeviceID + "-" + media.TotalPacket.ToString());
                    }

                    return;
                }

                FileStream fs = new FileStream(v_filename, FileMode.Create);
                string D = media.Data;
                string des;
                int len;
                int ntmp;
                string stmp;
                string imghex = "";

                for (int i = 1; i <= media.TotalPacket; i++)
                {
                    des = (string)media.MediaTable[i];
                    if (des != null)
                    {
                        imghex += des;
                        len = des.Length / 2;
                        for (int j = 1; j <= len; j++)
                        {
                            stmp = des.Substring(2 * (j - 1), 2);
                            ntmp = GwUtil.HexToInt(stmp);
                            fs.WriteByte((byte)ntmp);


                        }
                    }
                }
                fs.Flush();
                fs.Close();
                fs.Dispose();

                string key = media.DeviceID + media.MultiMediaID;




                lock (downSendMsgDic)
                {
                    if (downSendMsgDic.ContainsKey(key))
                    {
                        string media_flow = downSendMsgDic[key];
                        string sql = $"insert into lbs_media(dev_media_id,media_flow,media_type,media_format,media_path,event_code,channel,location,create_date)values('{media.MultiMediaID}','{media_flow}',{media.MultiMediaType},'{media.MultiMediaFormat}','{v_filename.Replace("\\", "/").Substring(2)}',{media.MultiMediaEvent},{media.ChannelID},'{data.Substring(0, 56)}',now());";
                        DBHelp.DBHelp.ExecSql(sql);
                        LogHelp.WriteeLog("", "save" + key + media_flow + v_filename.Replace("\\", "/").Substring(2));
                        downSendMsgDic.Remove(key);
                    }
                    else
                    {
                        LogHelp.WriteeLog("", "save" + key + "不存在的key");
                        string media_flow = "####";
                        string sql = $"insert into lbs_media(dev_media_id,media_flow,media_type,media_format,media_path,event_code,channel,location,create_date)values('{media.MultiMediaID}','{media_flow}',{media.MultiMediaType},'{media.MultiMediaFormat}','{v_filename.Replace("\\", "/").Substring(2)}',{media.MultiMediaEvent},{media.ChannelID},'{data.Substring(0, 56)}',now());";
                        downSendMsgDic.Add(key, sql);
                    }
                }




                LogHelp.WriteeLog("", "多媒体生成成功：" + v_filename);
                lock (MultiMediaList)
                {
                    MultiMediaList.Remove(media.DeviceID + "-" + media.TotalPacket.ToString());
                }



            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("", "保存多媒体文件失败：" + e.ToString());
            }
        }

        /// <summary>
        /// 6006 上报文本消息
        /// </summary>
        /// <param name="data"></param>
        private static void Handle6006Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;

            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x6006, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int ntype = body[0];
            byte[] bs = new byte[body.Length - 1];
            Buffer.BlockCopy(body, 1, bs, 0, bs.Length);
            string content = GwUtil.HexToStr(GwUtil.BytesToHex(bs));
            string SqlStr = "insert into " + HisDataBaseName + DateTime.Now.ToString("yyyy_MM_dd")
                    + ".dbo.UploadTable (PhoneNum,TypeID,TypeName,Data,UpLoadTime) values ('"
                    + phoneNumber + "','6006','终端上传文本消息','" + content + "', GetDate());";
            DBHelp.DBHelp.ExecSql(SqlStr);
        }

        /// <summary>
        /// 0201 位置信息查询应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0201Data(HandleData808 data)
        {
            string SerialNumber = GwUtil.IntToHex(GwUtil.ToInt16(data.body, 0), 4);
            //应答
            //string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(0x0201, 4) + "00";
            //byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            //SourceData sd = new SourceData();
            //sd.bs = setBuffers;
            //sd.Client = data.client;
            //PushSend(sd);

            //更新下发设备表
            string key1 = data.phoneNumber + "8201" + SerialNumber;
            lock (downSendMsgDic)
            {
                if (downSendMsgDic.ContainsKey(key1))
                {
                    string updateSql = $"update lbs_send_down set response='成功',response_time=now(),send_status=1  where send_id ={downSendMsgDic[key1]};";
                    AddToUpdateSqlList(updateSql);
                    downSendMsgDic.Remove(key1);
                }
            }

            byte[] bs = new byte[data.body.Length - 2];
            Buffer.BlockCopy(data.body, 2, bs, 0, bs.Length);
            data.body = bs;
            PositionUpLoadCache(data);
        }

        /// <summary>
        /// 6002 盲区补传
        /// </summary>
        /// <param name="data"></param>
        private static void Handle6002Data(HandleData808 data)
        {
            string phoneNumber = data.phoneNumber;
            int seqId = data.seqId;
            int encry = data.encry;
            bool subPackage = data.subPackage;
            bool multiMedia = data.multiMedia;
            int bodyLength = data.bodyLength;
            ushort totalPacket = data.totalPacket;
            ushort curPacket = data.curPacket;
            byte[] body = data.body;



            //应答
            string msgbody = GwUtil.IntToHex(seqId, 4) + GwUtil.IntToHex(0x6002, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            int count = GwUtil.ToInt16(body, 2);
            byte[] bs = new byte[body.Length - 4];
            Buffer.BlockCopy(body, 4, bs, 0, bs.Length);
            for (int i = 0; i < count; i++)
            {
                try
                {
                    int len = bs[0];
                    byte[] tmpbs = new byte[len];
                    Buffer.BlockCopy(bs, 1, tmpbs, 0, len);
                    Gps gps = GpsTool.HandleGps(tmpbs);
                    gps.PhoneNum = phoneNumber;

                    gps.DbName = HisDataBaseName + gps.GpsTime.ToString("yyyy_MM_dd");
                    gps.TableName = "HISTRACEINFO_" + gps.PhoneNum.Substring(gps.PhoneNum.Length - 2, 2);
                    PushGps(gps);

                    byte[] b = new byte[bs.Length - len - 1];
                    Buffer.BlockCopy(bs, 1 + len, b, 0, bs.Length - 1 - len);
                    bs = null;
                    bs = b;
                }
                catch (Exception ex)
                {
                    LogHelp.WriteeLog("Handle6002Data", ex.ToString());
                }
            }
        }

        /// <summary>
        /// 0500 车辆控制应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0500Data(HandleData808 data)
        {
            try
            {
                string SerialNumber = GwUtil.BytesToHex(data.body.Skip(0).Take(2).ToArray());

                byte[] bs = new byte[data.body.Length - 2];
                Buffer.BlockCopy(data.body, 2, bs, 0, bs.Length);
                data.body = bs;
                PositionUpLoadCache(data);

                //更新下发设备表
                string key1 = data.phoneNumber + "8500" + SerialNumber;
                lock (downSendMsgDic)
                {
                    if (downSendMsgDic.ContainsKey(key1))
                    {
                        string updateSql = $"update lbs_send_down set response='成功',response_time=now(),send_status=1  where send_id ={downSendMsgDic[key1]};";
                        AddToUpdateSqlList(updateSql);
                        downSendMsgDic.Remove(key1);
                    }
                }

            }
            catch (Exception e)
            {
                LogHelp.WriteeLog("", "车辆控制应答异常：" + e.ToString() + data.phoneNumber);
            }

        }

        /// <summary>
        /// 0102 终端鉴权
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0102Data(HandleData808 hldata)
        {
            string AuthCode = Encoding.Default.GetString(hldata.body);
            string ret = AuthCode == AuthenticationCode ? "00" : "01";

            if (ret == "00")
            {
                string updateStr = "UPDATE  `dev_gps_realtime` SET  `online_status` = 1,`update_time` = now() ,data_time=now() WHERE `device_id` = " + hldata.deviceInfo.deviceId + ";";
                string result = DBHelp.DBHelp.ExecSql(updateStr);
                if (result == "0")
                {
                    updateStr = $"insert into dev_gps_realtime (device_id,create_time,online_status,update_time,device_phone_num)values({hldata.deviceInfo.deviceId},now(),1,now(),'{hldata.deviceInfo.deviceNo}');";
                    DBHelp.DBHelp.ExecSql(updateStr);
                    updateStr = null;
                }
            }
            LogHelp.WriteeLog("", "终端鉴权：鉴权码，" + AuthCode + hldata.phoneNumber);

            string msgbody = GwUtil.IntToHex(hldata.seqId, 4) + GwUtil.IntToHex(0x0102, 4) + ret;
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, hldata.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = hldata.client;
            sd.deviceNo = hldata.phoneNumber;
            PushSend(sd);
        }


        /// <summary>
        /// 0100 终端注册
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0100Data(HandleData808 hldata)
        {
            try
            {
                #region 解析
                //省域ID
                int ProvincialId = GwUtil.ToInt16(hldata.body, 0);
                //市县域ID
                int CityId = GwUtil.ToInt16(hldata.body, 2);
                //制造商ID
                string ManufacturerId = GwUtil.Bytes2String(hldata.body, 4, 5);
                //终端型号
                string TerminalType;
                //终端ID
                string TerminalId;
                //车牌颜色
                int LicensePlateColor;
                //车牌号
                string VehicleLicensePlate;
                if (hldata.body.Length > 37)
                {
                    //终端型号
                    TerminalType = GwUtil.Bytes2String(hldata.body, 9, 8 + 12).Replace("\0", "");
                    //终端ID
                    TerminalId = GwUtil.Bytes2String(hldata.body, 17 + 12, 7);
                    //车牌颜色
                    LicensePlateColor = hldata.body[24 + 12];
                    //车牌号
                    VehicleLicensePlate = GwUtil.Bytes2String(hldata.body, 25 + 12, hldata.body.Length - 25 - 12);
                }
                else
                {
                    //终端型号
                    TerminalType = GwUtil.Bytes2String(hldata.body, 9, 8).Replace("\0", "");
                    //终端ID
                    TerminalId = GwUtil.Bytes2String(hldata.body, 17, 7);
                    //车牌颜色
                    LicensePlateColor = hldata.body[24];
                    //车牌号
                    VehicleLicensePlate = GwUtil.Bytes2String(hldata.body, 25, hldata.body.Length - 25 - 1);
                }
                #endregion
                DeviceRegisterInfo RegisterInfo = new DeviceRegisterInfo();
                RegisterInfo.ShengYuID = ProvincialId.ToString();
                RegisterInfo.ShiXianYuID = CityId.ToString();
                RegisterInfo.ZhiZaoShangID = ManufacturerId;
                RegisterInfo.DevicemodelNumber = TerminalType;
                RegisterInfo.DeviceID = TerminalId.Trim(' ').Trim('\0'); ;
                RegisterInfo.PlateColor = LicensePlateColor;
                RegisterInfo.PlateNumber = VehicleLicensePlate.Trim(' ').Trim('\0');

                string s = (RegisterInfo.ToString()).Replace("\0", "");

                string ret = CheckRegister(hldata.phoneNumber.TrimStart('0'), RegisterInfo);
                LogHelp.WriteeLog("", "终端注册：" + s + " 结果：" + ret);
                string MsgBody = string.Empty;

                if (ret == "00")
                {

                    MsgBody = GwUtil.IntToHex(hldata.seqId, 4) + ret + GwUtil.StrToHex(AuthenticationCode);

                    hldata.deviceInfo = SelectDeviceInfo(hldata.phoneNumber);

                    string updateStr = "UPDATE  `dev_gps_realtime` SET  `online_status` = 1,`update_time` = now() ,data_time=now()  WHERE `device_id` = " + hldata.deviceInfo.deviceId + ";";
                    string result = DBHelp.DBHelp.ExecSql(updateStr);

                    if (result == "0")
                    {
                        string insertSql = $"insert into dev_gps_realtime (device_id,create_time,online_status,update_time,device_phone_num)values({hldata.deviceInfo.deviceId},now(),1,now(),'{hldata.deviceInfo.deviceNo}');";
                        DBHelp.DBHelp.ExecSql(insertSql);
                        insertSql = null;
                    }
                }
                else
                {
                    MsgBody = GwUtil.IntToHex(hldata.seqId, 4) + ret;
                }

                byte[] setBuffers = GwUtil.BuildPackage(0x8100, hldata.phoneNumber, MsgBody);
                SourceData sd = new SourceData();
                sd.bs = setBuffers;
                sd.Client = hldata.client;
                sd.deviceNo = hldata.phoneNumber;
                PushSend(sd);
                LogHelp.WriteeLog("", "注册应答:" + hldata.phoneNumber + "  " + GwUtil.BytesToHex(setBuffers));
                MsgBody = null;
                RegisterInfo = null;
            }
            catch (System.Exception ex)
            {
                LogHelp.WriteeLog("", "终端注册 处理异常：" + ex.Message + "|" + ex.ToString());
                LogHelp.WriteeLog("", "终端注册 处理异常：" + ex.Message + "|" + ex.ToString() + hldata.phoneNumber);
            }
        }

        /// <summary>
        /// 查询车辆是否注册new
        /// </summary>
        /// <param name="DeviceID"></param>
        /// <param name="RegisterInfo"></param>
        /// <returns></returns>
        private static string CheckRegister(string DeviceID, DeviceRegisterInfo RegisterInfo)
        {
            /*
            如果车牌号或者车辆颜色不对的话，要回复数据库中无该车辆，若终端ID不对的话，回复无该终端。

             * 
             0：成功；1：车辆已被注册；2：数据库中无该车辆；
             3：终端已被注册；4：数据库中无该终端
             * 
             * select Register, vehicle_color, TerminalID from DeviceInfo where  PhoneNum='013100000002'
             */
            string ret = string.Empty;
            string SqlStr = "select   device_id  from base_device where device_phone_num = " + QuotedStr(DeviceID);

            int count = DBHelp.DBHelp.ExSelectCout(SqlStr);
            if (count > 0)
            {
                ret = "00"; //成功
            }
            else
            {
                ret = "04"; //数据库中无该终端

            }
            return ret;
        }
        private static string QuotedStr(string s)
        {
            return "'" + s + "'";
        }


        /// <summary>
        /// 0003 终端注销
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0003Data(HandleData808 data)
        {
            string str = "00";
            //DeviceInfo dev = redis.HashGet<DeviceInfo>("DeviceInfo", data.phoneNumber.TrimStart('0'));
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(0x0003, 4) + str;
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);

            //string sqlInsert = "insert into Ter_DeviceLogout (DeviceNo,logoutNumber,DsHeadId,DepartMentId,LogoutTime,JoinDate)values('" + data.phoneNumber.TrimStart('0') + "'," + data.seqId + "," + dev.DsHeadId + "," + dev.DepartMentId + ",getdate(),getdate());";
            //AddToUpdateSqlList(sqlInsert);

            //string sql = "update lbs_car set Register =0 where sim_card = '" + data.phoneNumber.TrimStart('0') + "';";
            //AddToUpdateSqlList(sql);
        }

        /// <summary>
        /// 0001 终端通用应答
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0001Data(HandleData808 data)
        {
            int n808Serial = GwUtil.ToInt16(data.body, 0);
            string CommandID = GwUtil.IntToHex(GwUtil.ToInt16(data.body, 2), 4);
            byte ret = data.body[4];
            string SRet = string.Empty;
            switch (ret)
            {
                case 0: SRet = "成功"; break;
                case 1: SRet = "失败"; break;
                case 2: SRet = "消息有误"; break;
                case 3: SRet = "不支持"; break;
            }


            LogHelp.WriteeLog("Handle0001Data", data.phoneNumber + "=8300=" + SRet);



            //string key = data.phoneNumber + CommandID + GwUtil.IntToHex(n808Serial, 4);
            //lock (downSendMsgDic)
            //{
            //    if (downSendMsgDic.ContainsKey(key))
            //    {
            //        string update8103 = $"update lbs_send_down set response='{SRet}',response_time=now(),send_status=1  where response is  null and send_id ={downSendMsgDic[key]};";
            //        AddToUpdateSqlList(update8103);
            //        downSendMsgDic.Remove(key);
            //    }
            //}


            //DevInfo dev = redis.HashGet<DevInfo>("allCarsCache", data.phoneNumber.TrimStart('0'));
            //if (dev == null)
            //{
            //    return;
            //}


        }
        private static void SelectCurDayTaskPlan(string workPlanType)
        {
            string date = DateTime.Now.ToString("yyyy-MM-dd");
            string sqlStr = "SELECT twp.dept_id, tpd.plan_detail_id, twp.work_plan_id,tts.work_team_id,twp.person_id,dev.device_id,tts.fence_id,tts.start_span,tts.end_span" +
                ", dev.device_phone_num,fen.radius,fen.latlng,fen.check_points,fen.fence_type,twp.car_id " +
                " FROM task_plan_detail as tpd,task_team_span as tts,task_work_plan as twp,base_person as per,base_device as dev,base_fence as fen" +
                " where tpd.effect_date = '" + date + "'" +
                " and tpd.detail_status = 1" +
                " and tpd.work_plan_id = twp.work_plan_id" +
                " and tpd.work_team_id = tts.work_team_id" +
                " and twp.person_id = per.person_id" +
                " and per.device_id = dev.device_id" +
                " and tts.fence_id = fen.fence_id" +
                " and twp.work_plan_type = '" + workPlanType + "';";
            if (workPlanType == "car")
            {
                sqlStr = "SELECT twp.dept_id,  tpd.plan_detail_id, twp.work_plan_id,tts.work_team_id,tts.person_id,dev.device_id,tts.fence_id,tts.start_span,tts.end_span, dev.device_phone_num,fen.radius,fen.latlng,fen.check_points,fen.fence_type,twp.car_id  " +
                    " FROM task_plan_detail as tpd,task_team_span as tts,task_work_plan as twp,base_person as per,base_device as dev,base_fence as fen ,base_car as car " +
                    " where tpd.effect_date = '" + date + "'" +
                    " and tpd.detail_status = 1 " +
                    " and twp.work_plan_type = 'car' " +
                    " and tpd.work_plan_id = twp.work_plan_id " +
                    " and tpd.work_team_id = tts.work_team_id " +
                    " and tts.person_id = per.person_id " +
                    " and car.device_id = dev.device_id " +
                    " and tts.fence_id = fen.fence_id " +
                    " and twp.car_id = car.car_id;";
            }
            DataTable devDT1 = DBHelp.DBHelp.QueryDataFromDB(sqlStr);
            if (devDT1 != null && devDT1.Rows.Count > 0)
            {
                for (int i = 0; i < devDT1.Rows.Count; i++)
                {
                    int planDetailId = devDT1.Rows[i]["plan_detail_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["plan_detail_id"].ToString());
                    int carId = devDT1.Rows[i]["car_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["car_id"].ToString());
                    int deviceId = devDT1.Rows[i]["device_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["device_id"].ToString());
                    string deviceNo = devDT1.Rows[i]["device_phone_num"] == DBNull.Value ? "" : devDT1.Rows[i]["device_phone_num"].ToString();
                    int workPlanId = devDT1.Rows[i]["work_plan_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_plan_id"].ToString());
                    int workTeamId = devDT1.Rows[i]["work_team_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["work_team_id"].ToString());
                    int personId = devDT1.Rows[i]["person_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["person_id"].ToString());
                    string fenceType = devDT1.Rows[i]["fence_type"] == DBNull.Value ? "" : devDT1.Rows[i]["fence_type"].ToString();
                    string startSpan = devDT1.Rows[i]["start_span"] == DBNull.Value ? "" : devDT1.Rows[i]["start_span"].ToString();
                    string endSpan = devDT1.Rows[i]["end_span"] == DBNull.Value ? "" : devDT1.Rows[i]["end_span"].ToString();
                    int radius = devDT1.Rows[i]["radius"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["radius"].ToString());
                    string latlng = devDT1.Rows[i]["latlng"] == DBNull.Value ? "" : devDT1.Rows[i]["latlng"].ToString();
                    string checkPoints = devDT1.Rows[i]["start_span"] == DBNull.Value ? "" : devDT1.Rows[i]["check_points"].ToString();
                    int fenceId = devDT1.Rows[i]["fence_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["fence_id"].ToString());
                    int dept_id = devDT1.Rows[i]["dept_id"] == DBNull.Value ? 0 : int.Parse(devDT1.Rows[i]["dept_id"].ToString());
                    CurDayTaskPlan curDayTaskPlan = new CurDayTaskPlan();
                    curDayTaskPlan.deviceId = deviceId;
                    curDayTaskPlan.deviceNo = deviceNo;
                    curDayTaskPlan.fenceId = fenceId;
                    curDayTaskPlan.fenceType = fenceType;
                    curDayTaskPlan.personId = personId;
                    curDayTaskPlan.workPlanId = workPlanId;
                    curDayTaskPlan.workTeamId = workTeamId;
                    curDayTaskPlan.radius = radius;
                    curDayTaskPlan.startSpan = TimeSpan.Parse(startSpan);
                    curDayTaskPlan.endSpan = TimeSpan.Parse(endSpan);
                    curDayTaskPlan.checkPoints = checkPoints;
                    curDayTaskPlan.latlng = latlng;
                    curDayTaskPlan.workState = 0;
                    curDayTaskPlan.carId = carId;
                    curDayTaskPlan.workPlanType = workPlanType;
                    curDayTaskPlan.planDetailId = planDetailId;
                    curDayTaskPlan.deptId = dept_id;
                    //string oldKey = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd") + ":" + curDayTaskPlan.deviceNo;
                    string key = date + ":" + curDayTaskPlan.deviceNo;
                    string hashKey = startSpan + "_" + endSpan;
                    curDayTaskPlan.key = key;
                    curDayTaskPlan.hashKey = hashKey;
                    if (!redis.HashExists(key, hashKey))
                    {
                        string insertSql = "INSERT INTO `report_check_work`(plan_detail_id,effect_date,`work_plan_id`, `work_team_id`, `person_id`, `device_id`, `fence_id`, `start_span`, `end_span`, `create_time`, `update_time`,car_id,work_plan_type) VALUES" +
                            $" ({planDetailId}, '{date}',  {workPlanId}, {workTeamId}, {personId}, {deviceId}, {fenceId}, '{startSpan}', '{endSpan}', NOW(), NOW(),{carId},'{workPlanType}');SELECT LAST_INSERT_ID();";
                        object obj = DBHelp.DBHelp.executeSql(insertSql);
                        curDayTaskPlan.checkWorkId = int.Parse(obj?.ToString());
                        redis.HashSet<CurDayTaskPlan>(key, hashKey, curDayTaskPlan);

                    }

                }
            }



        }
        /// <summary>
        /// 0002 终端心跳
        /// </summary>
        /// <param name="data"></param>
        private static void Handle0002Data(HandleData808 data)
        {
            //string sqlStr = "select device_id from  res_device  where device_phone_num = '" + data.phoneNumber.TrimStart('0') + "';";
            //object device_id = DBHelp.DBHelp.executeSql(sqlStr);
            //if (device_id != null)
            //{
            string updateStr = "UPDATE  `dev_gps_realtime` SET  `online_status` = 1,`update_time` = now(),data_time=now()  WHERE `device_id` = " + data.deviceInfo.deviceId + ";";
            string result = DBHelp.DBHelp.ExecSql(updateStr);
            if (result == "0")
            {
                string insertSql = $"insert into dev_gps_realtime (device_id,create_time,online_status,update_time,device_phone_num)values({data.deviceInfo.deviceId},now(),1,now(),'{data.deviceInfo.deviceNo}');";
                DBHelp.DBHelp.ExecSql(insertSql);
            }
            //}

            //应答
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(data.msgId, 4) + "00";
            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);
            SaveHeart(data.phoneNumber, DateTime.Now);
        }

        /// <summary>
        /// 0200 位置信息汇报
        /// </summary>
        /// <param name="data"></param>
        public static void Handle0200Data(HandleData808 data)
        {
            PositionUpLoadCache(data);




            //应答
            string msgbody = GwUtil.IntToHex(data.seqId, 4) + GwUtil.IntToHex(data.msgId, 4) + "00";

            byte[] setBuffers = GwUtil.BuildPackage(0x8001, data.phoneNumber, msgbody);
            SourceData sd = new SourceData();
            sd.bs = setBuffers;
            sd.Client = data.client;
            sd.deviceNo = data.phoneNumber;
            PushSend(sd);


            //DownSendUpdateIP(data.client, data.phoneNumber);

        }


        public static void PositionUpLoadCache(HandleData808 hldata)
        {
            Gps gps = GpsTool.HandleGps(hldata.body);
            gps.PhoneNum = hldata.phoneNumber;
            gps.deviceId = hldata.deviceInfo.deviceId.ToString();
            //gps.carId = hldata.deviceInfo.carId.ToString();
            //Task.Run(() => CalcCheckWork(gps));
            CalcCheckWork(gps,hldata.deviceInfo.deviceType);

        }

        private static void CalcCheckWork(Gps gps,string devType)
        {
      
            try
            {
              
                if (Math.Abs((gps.GpsTime - DateTime.Now).TotalDays) > 30)
                {
                    return;
                }
                Gps old = null;
                lock (GPSTable)
                {
                    if (GPSTable.ContainsKey(gps.PhoneNum))
                    {
                        old = GPSTable[gps.PhoneNum];
                    }
                }
           
                if (old != null && gps?.Attach?.OilMass > 0 && old?.Attach?.OilMass > 0 && "portable_locator".Equals(devType) && gps?.Attach?.Mileage>0 && old?.Attach?.Mileage>0)
                {
                 
                    decimal change = Math.Abs((decimal)(gps.Attach.OilMass - old.Attach.OilMass));
                    decimal changeMileage = Math.Abs((decimal)(gps.Attach.Mileage - old.Attach.Mileage)) / 10.0m;
                    decimal oil_mean = 0;
                    if (changeMileage != 0)
                    {
                        oil_mean = change / changeMileage;
                    }
                    if (change>0.01m)
                    {
                    object obj = DBHelp.DBHelp.executeSql("select car_id from base_car WHERE device_id=" + gps?.deviceId + ";");
                    int carId = 0;
                    if (obj != null && int.TryParse(obj.ToString(), out carId))
                    {
                        string sqlOil = "INSERT INTO  `report_car_oil`(`car_id`, `data_time`, `car_oil`, car_oil_state,`oil_changed`, `oil_mean`, `create_by`, `create_time`) VALUES " +
         $"( {carId}, '{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}', {gps.Attach.OilMass}, {gps.Attach.OilMassState}, {change},{oil_mean},'tcp', now());";
                        DBHelp.DBHelp.ExecSql(sqlOil);
                    }
                    }
                
                }

                if (gps != null && gps?.Longitude > 10 && gps?.Latitude > 10)
                {
                    try
                    {
                        UsePoiGetNew(gps);
                        DateTime dateTime = gps.GpsTime;
                        List<CurDayTaskPlan> curDayTaskPlans = redis.HashValues<CurDayTaskPlan>(dateTime.ToString("yyyy-MM-dd") + ":" + gps.PhoneNum);
                        foreach (var item in curDayTaskPlans)
                        {
                            //当前时间点，是否是工作时间段
                            if (item.startSpan.Add(TimeSpan.FromMinutes(-30)) <= dateTime.TimeOfDay && dateTime.TimeOfDay <= item.endSpan)
                            {
                                //object obj = DBHelp.DBHelp.executeSql($"select work_state from report_check_work where check_work_id={item.checkWorkId};");
                                //if (obj != null && int.Parse(obj.ToString()) == 0)
                                //{
                                //    item.workState = 0;
                                //}
                                switch (item.workState)
                                {
                                    case 0:

                                        bool isOut = CalcLeaveArea(item, gps);
                                        if (!isOut)
                                        {
                                            TimeSpan span = dateTime.TimeOfDay - item.startSpan;
                                            if (span.TotalMinutes > 30)
                                            {
                                                item.workState = 2;
                                            }
                                            else
                                            {
                                                item.workState = 1;
                                            }
                                            //UsePoiGetNew(gps);
                                            string update = $"update report_check_work set start_work_time='{gps.SgpsTime}',start_work_lat='{gps.PosY}',start_work_lng='{gps.PosX}',update_time=now(),work_state={item.workState} ,absence_reason=''  where check_work_id={item.checkWorkId}";
                                            DBHelp.DBHelp.ExecSql(update);
                                            update = null;
                                            redis.HashSet(item.key, item.hashKey, item);
                                        }
                                        else
                                        {
                                            string update = $"update report_check_work set  update_time=now(),absence_reason='未进工作区域' where check_work_id={item.checkWorkId}";
                                            DBHelp.DBHelp.ExecSql(update);
                                            update = null;
                                        }
                                        break;
                                    case 1:
                                    case 2:
                                        //计算报警，统计关键点
                                        try
                                        {
                                            CalcAlarm(gps, item);
                                        }
                                        catch (Exception ex)
                                        {
                                            LogHelp.WriteeLog("CalcAlarm", gps.PhoneNum + ex.ToString());
                                        }

                                        break;
                                }
                            }
                            TimeSpan ts = dateTime.TimeOfDay - item.endSpan;
                            if (ts.TotalMinutes >= 0 && ts.TotalMinutes <= 30 && (item.workState == 4))
                            {
                                bool isOut = CalcLeaveArea(item, gps);
                                if (!isOut)
                                {
                                    item.workState = 3;
                                    UpdateWorkState(item, gps);
                                }
                            }

                            if (ts.TotalMinutes < 0 && ts.TotalMinutes >= -10.0 && (item.workState == 1 || item.workState == 2))
                            {
                                bool isOut = CalcLeaveArea(item, gps);
                                if (!isOut)
                                {
                                    item.workState = 4;
                                    UpdateWorkState(item, gps);
                                }
                            }
                        }
                        curDayTaskPlans.Clear();
                        curDayTaskPlans = null;
                        //calcAlarm(gps);
                    }
                    catch (Exception ex)
                    {
                        LogHelp.WriteeLog("CalcCheckWorkException",gps.PhoneNum+ ex.ToString());
                    }
                    finally
                    {
                        UpdateDeviceGps(gps);
                        UpdateRedisGps(gps);
                        PushGps(gps);
                    }

                }

            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("CalcCheckWork",gps.PhoneNum + ex.ToString());

            }

       
        }

    
     

        private static void UpdateWorkState(CurDayTaskPlan item, Gps gps)
        {
            //UsePoiGetNew(gps);
            string update = $"update report_check_work set end_work_time='{gps.SgpsTime}',end_work_lat='{gps.PosY}',end_work_lng='{gps.PosX}',update_time=now(),work_state={  item.workState } where check_work_id={item.checkWorkId}";
            DBHelp.DBHelp.ExecSql(update);
            redis.HashSet(item.key, item.hashKey, item);
            update = null;
        }
        private static void CalcAlarm(Gps gps, CurDayTaskPlan curDayTaskPlan)
        {
 

            GpsInfo oldGps = redis.HashGet<GpsInfo>("GpsInfo", gps.PhoneNum);
            double minute = Math.Abs((gps.GpsTime - DateTime.Parse(oldGps.GpsTime)).TotalMinutes);
            if (minute < 30)
            {
                if (curDayTaskPlan.workPlanType.Equals("car"))
                {
                    int oldAcc = 0;
                    if (oldGps.AccState.Contains("开"))
                    {
                        oldAcc = 1;
                    }
                    if(oldAcc!= gps.TheStatus.Acc)
                    {
                        string acc_status = gps.TheStatus.Acc == 0 ? "off" : "on";
                        string insertSql = $"INSERT INTO `report_car_acc`(`person_id`, `car_id`, `fence_id`, `data_time`, `acc_status`, `create_by`, `create_time`) VALUES " +
            $"({curDayTaskPlan.personId}, {curDayTaskPlan.carId}, {curDayTaskPlan.fenceId}, '{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}', '{acc_status}', 'tcp', now());";
                        DBHelp.DBHelp.ExecSql(insertSql);
                    }
 
                    CalcOverSpeedAlarm(curDayTaskPlan, gps);
                    CalcLeaveAreaAlarm(curDayTaskPlan, gps, "car_out_of_fence");
                    CalcStopAreaAlarm(curDayTaskPlan, gps, "car_stay");
                }
                else
                {
                    CalcLeaveAreaAlarm(curDayTaskPlan, gps, "person_out_of_fence");

                    CalcStopAreaAlarm(curDayTaskPlan, gps, "person_stay");
                }


            }
            else
            {
                List<string> keys = redis.HashKeys("AlarmRule");
                foreach (var item in keys)
                {
                    string dataKey = gps.GpsTime.ToString("yyyy-MM-dd") + gps.deviceId + ":" + item;
                    redis.HashDelete("AlarmNow", dataKey);
                }
            }


        }

        private static void CalcStopAreaAlarm(CurDayTaskPlan curDayTaskPlan, Gps gps, string alarmType)
        {
            AlarmRule alarmRule = redis.HashGet<AlarmRule>("AlarmRule", alarmType);
            if (!alarmRule.enabled)
            {
                return;
            }
            GpsInfo oldGps = redis.HashGet<GpsInfo>("GpsInfo", gps.PhoneNum);
            string dataKey = gps.GpsTime.ToString("yyyy-MM-dd") + gps.deviceId + ":" + alarmRule.alarm_type;

            bool distance = OutInAreaLineAlarm.GetTwoPointsDistance(new Point(gps.PosX, gps.PosY), new Point(oldGps.LongitudeNew, oldGps.LatitudeNew)) > 100 ? true : false;

            if (!distance)
            {
                AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                if (alarm != null)
                {

                    double drationTime = (gps.GpsTime - alarm.startTime).TotalMinutes;
                    if (drationTime > alarmRule.stop_max_minute)
                    {
                        if (String.IsNullOrEmpty(alarm.alarmId))
                        {
                            string sqlInsert = $"INSERT INTO `alarm_event`(fence_id,dept_id, `device_id`,  `person_id`,  `work_plan_id`, `work_team_id`, `target_type`, `alarm_type`, `event_start`, `event_end`, `event_finish`,  `persist_time`,create_time,update_time ) VALUES " +
                                                                                                  $"({curDayTaskPlan.fenceId},{curDayTaskPlan.deptId},{gps.deviceId}, {curDayTaskPlan.personId}, {curDayTaskPlan.workPlanId},{curDayTaskPlan.workTeamId},'{curDayTaskPlan.workPlanType}','{alarmRule.alarm_type}','{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', '{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', 0,{drationTime}, now(),now());select @@IDENTITY;";
                            object eventId = DBHelp.DBHelp.executeSql(sqlInsert);
                            alarm.alarmId = eventId.ToString();
                            redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                            sqlInsert = null;
                        }
                        else
                        {
                            int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                            string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time} where event_id ={alarm.alarmId};";
                            DBHelp.DBHelp.ExecSql(sqlUpdate);
                            sqlUpdate = null;
                        }
                    }

                }
                else
                {
                    alarm = new AlarmNow(alarmRule, gps.GpsTime);
                    alarm.times = 0;
                    redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                }
            }
            else
            {
                if (redis.HashExists("AlarmNow", dataKey))
                {
               
                    AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                    int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                    string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time},event_finish=1 where event_id ={alarm.alarmId};";
                    DBHelp.DBHelp.ExecSql(sqlUpdate);
                    redis.HashDelete("AlarmNow", dataKey);
                }
            }


        }

        private static void CalcOverSpeedAlarm(CurDayTaskPlan curDayTaskPlan, Gps gps)
        {
            AlarmRule alarmRule = redis.HashGet<AlarmRule>("AlarmRule", "car_overspeed");
            if (!alarmRule.enabled)
            {
                return;
            }
            //GpsInfo oldGps = redis.HashGet<GpsInfo>("GpsInfo", gps.PhoneNum);
            string dataKey = gps.GpsTime.ToString("yyyy-MM-dd") + gps.deviceId + ":" + alarmRule.alarm_type;

            bool distance = gps.Speed > alarmRule.oil_waste ? true : false;

            if (!distance)
            {
                AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                if (alarm != null)
                {

                    double drationTime = (gps.GpsTime - alarm.startTime).TotalMinutes;
                    if (drationTime > alarmRule.stop_max_minute)
                    {
                        if (String.IsNullOrEmpty(alarm.alarmId))
                        {
                            string sqlInsert = $"INSERT INTO `alarm_event`(fence_id,dept_id, `device_id`,  `person_id`,  `work_plan_id`, `work_team_id`, `target_type`, `alarm_type`, `event_start`, `event_end`, `event_finish`,  `persist_time`,create_time,update_time ) VALUES " +
                                                                                                     $"({curDayTaskPlan.fenceId},{curDayTaskPlan.deptId},{gps.deviceId}, {curDayTaskPlan.personId}, {curDayTaskPlan.workPlanId},{curDayTaskPlan.workTeamId},'{curDayTaskPlan.workPlanType}','{alarmRule.alarm_type}','{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', '{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', 0,{drationTime}, now(),now());select @@IDENTITY;";
                            object eventId = DBHelp.DBHelp.executeSql(sqlInsert);
                            alarm.alarmId = eventId.ToString();
                            redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                            sqlInsert = null;
                        }
                        else
                        {
                            int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                            string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time} where event_id ={alarm.alarmId};";
                            DBHelp.DBHelp.ExecSql(sqlUpdate);
                            sqlUpdate = null;
                        }
                    }

                }
                else
                {
                    alarm = new AlarmNow(alarmRule, gps.GpsTime);
                    alarm.times = 0;
                    redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                }
            }
            else
            {
                if (redis.HashExists("AlarmNow", dataKey))
                {
                  
                    AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                    int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                    string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time},event_finish=1 where event_id ={alarm.alarmId};";
                    DBHelp.DBHelp.ExecSql(sqlUpdate);
                    redis.HashDelete("AlarmNow", dataKey);
                }
            }


        }

        //
        private static bool CalcLeaveArea(CurDayTaskPlan curDayTaskPlan, Gps gps)
        {
            bool distance = false;
            if (curDayTaskPlan.fenceType == "circle")
            {
                Point point = new Point(curDayTaskPlan.latlng);

                distance = OutInAreaLineAlarm.GetTwoPointsDistance(new Point(gps.PosX, gps.PosY), point) > curDayTaskPlan.radius ? true : false;
            }
            else if (curDayTaskPlan.fenceType == "rectangle")
            {

                string[] AreaList = curDayTaskPlan.latlng.Split('|');


                List<Point> listPoint = new List<Point>();

                Point leftLower = new Point(AreaList[0]);
                Point rightUpper = new Point(AreaList[1]);

                Point leftUpper = new Point(rightUpper.getX(), leftLower.getY());
                Point rightLower = new Point(leftLower.getX(), rightUpper.getY());
                //获取矩形的点
                listPoint.Add(leftUpper);
                listPoint.Add(rightUpper);
                listPoint.Add(rightLower);
                listPoint.Add(leftLower);


                distance = OutInAreaLineAlarm.PoinWithPolygon(new Point(gps.PosX, gps.PosY), listPoint) == PointRelationEnum.POINT_OUT_SCOPE ? true : false;
            }
            else if (curDayTaskPlan.fenceType == "polygon")
            {
                List<Point> listPoint = new List<Point>();
                string[] AreaList = curDayTaskPlan.latlng.Split('|');
                foreach (string latLng in AreaList)
                {
                    Point point = new Point(latLng);
                    listPoint.Add(point);
                }
                distance = OutInAreaLineAlarm.PoinWithPolygon(new Point(gps.PosX, gps.PosY), listPoint) == PointRelationEnum.POINT_OUT_SCOPE ? true : false;

            }
            return distance;
        }


        private static void CalcLeaveAreaAlarm(CurDayTaskPlan curDayTaskPlan, Gps gps, string alarmType)
        {
            AlarmRule alarmRule = redis.HashGet<AlarmRule>("AlarmRule", alarmType);
            if (!alarmRule.enabled)
            {
                return;
            }
            string dataKey = gps.GpsTime.ToString("yyyy-MM-dd") + gps.deviceId + ":" + alarmRule.alarm_type;
            bool distance = CalcLeaveArea(curDayTaskPlan, gps);


            if (distance)//区域外
            {
                AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                if (alarm != null)
                {
                    double drationTime = (gps.GpsTime - alarm.startTime).TotalMinutes;
                    if (drationTime > alarmRule.out_max_minute)//超时
                    {
                        if (String.IsNullOrEmpty(alarm.alarmId))
                        {
                            string sqlInsert = $"INSERT INTO `alarm_event`(fence_id,dept_id, `device_id`,  `person_id`,  `work_plan_id`, `work_team_id`, `target_type`, `alarm_type`, `event_start`, `event_end`, `event_finish`,  `persist_time`,create_time,update_time ) VALUES " +
                                                                                                   $"({curDayTaskPlan.fenceId},{curDayTaskPlan.deptId},{gps.deviceId}, {curDayTaskPlan.personId}, {curDayTaskPlan.workPlanId},{curDayTaskPlan.workTeamId},'{curDayTaskPlan.workPlanType}','{alarmRule.alarm_type}','{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', '{alarm.startTime.ToString("yyyy-MM-dd HH:mm:ss")}', 0,{drationTime}, now(),now());select @@IDENTITY;";
                            object eventId = DBHelp.DBHelp.executeSql(sqlInsert);
                            alarm.alarmId = eventId.ToString();
                            redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                            sqlInsert = null;
                        }
                        else
                        {
                            int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                            string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time} where event_id ={alarm.alarmId};";
                            DBHelp.DBHelp.ExecSql(sqlUpdate);
                        }
                    }

                }
                else
                {
                    alarm = new AlarmNow(alarmRule, gps.GpsTime);
                    alarm.times = 0;
                    redis.HashSet<AlarmNow>("AlarmNow", dataKey, alarm);
                }
            }
            else
            {
                if (redis.HashExists("AlarmNow", dataKey))
                {

                    AlarmNow alarm = redis.HashGet<AlarmNow>("AlarmNow", dataKey);
                    int persist_time = (int)(gps.GpsTime - alarm.startTime).TotalMinutes;
                    string sqlUpdate = $"update alarm_event set update_time=now(),event_end='{gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}' , persist_time={persist_time},event_finish=1 where event_id ={alarm.alarmId};";
                    DBHelp.DBHelp.ExecSql(sqlUpdate);

                    redis.HashDelete("AlarmNow", dataKey);
                }
            }


        }


        public static string get_uft8(string unicodeString)
        {
            UTF8Encoding utf8 = new UTF8Encoding();
            Byte[] encodedBytes = utf8.GetBytes(unicodeString);
            String decodedString = utf8.GetString(encodedBytes);
            return decodedString;
        }
        private static void SaveHeart(string PhoneNum, DateTime HeartTime)
        {
            lock (GPSTable)
            {
                if (GPSTable.ContainsKey(PhoneNum))
                {
                    if (GPSTable[PhoneNum].HeartTime < HeartTime)
                        GPSTable[PhoneNum].HeartTime = HeartTime;
                }
                else
                {
                    Gps gps = new Gps();
                    gps.PhoneNum = PhoneNum;
                    gps.HeartTime = HeartTime;
                    GPSTable.Add(PhoneNum, gps);
                }
            }
        }

        private static void UpdateRedisGps(Gps gps, int uploadMode = 1)
        {
            GpsInfo gpsInfo = Gps2RedisGps(gps);
            gpsInfo.Uploadmode = uploadMode;
            lock (_redisGpsCacheQ)
            {
                _redisGpsCacheQ.Enqueue(gpsInfo);
            }

        }

        private static GpsInfo Gps2RedisGps(Gps gps)
        {
            GpsInfo gpsInfo = new GpsInfo();
            gpsInfo.DeviceNo = gps.PhoneNum.TrimStart('0');

            gpsInfo.GpsTime = gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss");
            gpsInfo.LongitudeOld = gps.Longitude;
            gpsInfo.LatitudeOld = gps.Latitude;
            gpsInfo.LongitudeNew = gps.PosX;
            gpsInfo.LatitudeNew = gps.PosY;

            gpsInfo.Height = gps.high;
            gpsInfo.GpsSpeed = (gps.Speed / 10.0).ToString();
            gpsInfo.Direction = gps.Direction;
            gpsInfo.Mileage = gps.Attach.Mileage;
            gpsInfo.Speed = gps.Attach.RunSpeed.ToString();


            if (gps.TheStatus.ElectricStatus == 0)
            {
                gpsInfo.PowerState = "车辆电路正常";
            }
            else
            {
                gpsInfo.PowerState = "车辆电路断开";
            }

            if (gps.TheStatus.Location == 0)
            {
                gpsInfo.GpsState = "定位无效";
            }
            else
            {
                gpsInfo.GpsState = "定位正常";
            }


            gpsInfo.Location = gps.RegionInfo + gps.PlaceInfo;

            if (gps.TheStatus.Acc == 0)
            {
                gpsInfo.AccState = "ACC 关";
            }
            else
            {
                gpsInfo.AccState = "ACC 开";
            }

            if (gps.Speed > 0)
            {
                if (gpsInfo.AccState == "ACC 开")
                {
                    gpsInfo.CarState = "行驶";
                }
                else
                {
                    gpsInfo.CarState = "熄火";
                }
            }
            else
            {
                gpsInfo.CarState = gpsInfo.AccState == "ACC 关" ? "熄火" : "停车";
            }
            //gpsInfo.Alarm = gps.TheAlarm.
            if (gps.alarm > 0)
            {
                gpsInfo.isAlarm = true;
            }
            else
            {
                gpsInfo.isAlarm = false;
            }
            gpsInfo.UpdateDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");



            return gpsInfo;
        }
        #region  缓存GPS数据 
        private static void UpdateDeviceGps(Gps gps)
        {
            lock (GPSTable)
            {
                if (GPSTable.ContainsKey(gps.PhoneNum))
                {
                    gps.LastUpdateTime = (GPSTable[gps.PhoneNum]).LastUpdateTime;
                    GPSTable[gps.PhoneNum] = gps;
                    TimeSpan ts1 = DateTime.Now - gps.LastUpdateTime;
                    if (ts1.TotalSeconds >= UpdatePositionInterval)
                    {
                        string sql = UpdateThisHistory(gps);
                        AddToUpdateSqlList(sql);
                        (GPSTable[gps.PhoneNum]).LastUpdateTime = DateTime.Now;
                    }
                }
                else
                {
                    string sql = UpdateThisHistory(gps);
                    AddToUpdateSqlList(sql);
                    gps.LastUpdateTime = DateTime.Now;
                    GPSTable.Add(gps.PhoneNum, gps);
                }
            }
        }
        private static string UpdateThisHistory(Gps gps)
        {
            //string sqlStr = "select device_id from  res_device  where device_phone_num = '" + gps.PhoneNum + "';";

            //object device_id = DBHelp.DBHelp.executeSql(sqlStr);
            //if (device_id != null)
            //{
            string updateStr = "UPDATE `dev_gps_realtime` SET  dev_state='" + gps.statusDetail + "',`lat` = '" + gps.PosY + "', `lng` = '" + gps.PosX + "', `data_time` = '" + gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss") + "', `online_status` = 1,`speed` = " + gps.Speed + ", `direction` = " + gps.Direction + ", `mileage` = " + gps.Attach.Mileage + ",`car_location` = '" + gps.RegionInfo + gps.PlaceInfo + "', `update_time` = now() WHERE `device_id` = " + gps.deviceId + ";";
            //string updateStr = "UPDATE `dev_gps_realtime` SET  dev_state='" + gps.statusDetail + "',`lat` = '" + gps.Latitude + "', `lng` = '" + gps.Longitude + "', `data_time` = '" + gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss") + "', `online_status` = 1,`speed` = " + gps.Speed + ", `direction` = " + gps.Direction + ", `mileage` = " + gps.Attach.Mileage + ",`car_location` = '" + gps.RegionInfo + gps.PlaceInfo + "', `update_time` = now() WHERE `device_id` = " + device_id + ";";
            //string result = DBHelp.DBHelp.ExecSql(updateStr);
            //if (result == "0")
            //{
            //    string insertSql = $"insert into dev_gps_realtime (device_id,create_time,online_status,update_time)values({data.deviceInfo.deviceId},now(),1,now());";
            //    DBHelp.DBHelp.ExecSql(insertSql);
            //}


            //string updateStr = $"INSERT INTO `dev_gps_realtime`(`device_id`, `lat`, `lng`, `data_time`, `online_status`, `alarm_code`, `alarm_type`, `hight`, `speed`, `direction`, `mileage`, `oil_mass`, `voltage_level`, `gsm_signal`, `dev_state`, `car_location`, `create_time`, `update_time`) VALUES({gps.deviceId}, '{gps.PosY}', '{gps.PosX}', '{ gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}', 1, NULL, NULL, NULL, 4.00, 131, 0, NULL, NULL, NULL, '定位',NULL, now(),now()) ON DUPLICATE KEY UPDATE";
            //updateStr += $" `device_id` = {gps.deviceId},  dev_state='" + gps.statusDetail + "',`lat` = '" + gps.PosY + "', `lng` = '" + gps.PosX + "', `data_time` = '" + gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss") + "', `online_status` = 1,`speed` = " + gps.Speed + ", `direction` = " + gps.Direction + ", `mileage` = " + gps.Attach.Mileage + ",`car_location` = '" + gps.RegionInfo + gps.PlaceInfo + "', `update_time` = now();";

            return updateStr;
            //}
            //return "";

        }
        #endregion






        /// <summary>
        /// 插入报警事件表
        /// </summary>
        /// <param name="GData"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="RegionInfo"></param>
        /// <param name="PlaceInfo"></param>
        private static void InsertHisAlarm(Gps GData, double x, double y, string RegionInfo, string PlaceInfo)
        {

            if (GData.TheStatus.Location == 0)
            {
                LogHelp.WriteeLog("", "InsertHisAlarm, 未定位，不予插入报警表,devid:" + GData.PhoneNum);
                return;
            }
            string Status = GetCarStatus(GData.Speed, GData.TheStatus.Acc);

            GpsInfo gpsOld = redis.HashGet<GpsInfo>("GpsInfo", GData.PhoneNum);

            int alarm_status = 2;
            if (GData.alarmDetail.Contains("预警"))
            {
                alarm_status = 1;
            }
            if (gpsOld != null)
            {
                DevInfo dev = redis.HashGet<DevInfo>("allCarsCache", GData.PhoneNum);
                if (GData.alarm > 0 && gpsOld.isAlarm)//最新缓存是报警，并且收到的也是报警，更新事件表报警结束时间
                {
                    LogHelp.WriteeLog("", "更新报警事件表");
                    string updateAlarmEvent = $"update lbs_car_event set event_end='{GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}',alarm_type='{ GData.alarmDetail}',alarm_status={alarm_status} where event_id in (select max_id from (select max(event_id) as max_id from lbs_car_event where car_id={dev.carId} and event_finish=0 ) as a );";
                    AddToUpdateSqlList(updateAlarmEvent);

                }
                else if (GData.alarm == 0 && gpsOld.isAlarm)
                {
                    LogHelp.WriteeLog("", "结束报警事件表");
                    string updateAlarmEvent = $"update lbs_car_event set event_end='{GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}',event_finish=1 where event_id in (select max_id from (select max(event_id) as max_id from lbs_car_event where car_id={dev.carId} and event_finish=0 ) as a );";
                    AddToUpdateSqlList(updateAlarmEvent);

                }
                else if (GData.alarm > 0 && !gpsOld.isAlarm)
                {
                    LogHelp.WriteeLog("", "插入报警事件表");
                    string updateAlarmEvent = $"insert into lbs_car_event(car_id,event_start,event_end,event_finish,alarm_type,alarm_status,persist_time,create_date)values({dev.carId},'{GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}','{GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")}',0,'{GData.alarmDetail}',{alarm_status},0,now()); select @@IDENTITY;";
                    //AddToUpdateSqlList(updateAlarmEvent);
                    object eventId = DBHelp.DBHelp.executeSql(updateAlarmEvent);
                    Dictionary<String, Object> data = new Dictionary<String, Object>
                    {
                        {"msgType",1},
                        {"eventId",eventId},
                        {"carId",dev.carId},
                        {"licnum", dev.licnum},
                        {"plateColor", dev.plateColor},
                        {"simCard", dev.simCard},
                        {"event_start", GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")},
                        {"event_end", GData.GpsTime.ToString("yyyy-MM-dd HH:mm:ss")},
                        {"alarm_type", GData.alarmDetail},
                        {"alarm_status", alarm_status}
                    };
                    string json = JsonConvert.SerializeObject(data, Formatting.None);
                    DownMsgToWeb(get_uft8(json));

                    //sendMsg2Web(json);



                }
            }
            //if (ltalarm.Count > 0)
            //    WcfTool.InsertAlarmToDB(ltalarm);
        }

        /// <summary>
        /// 获取区域类型
        /// </summary>
        /// <param name="nType"></param>
        /// <returns></returns>
        private static string GetAreaTypeName(int nType)
        {
            string ret = string.Empty;
            switch (nType)
            {
                case 0:
                    ret = "无特定位置";
                    break;
                case 1:
                    ret = "圆形区域";
                    break;
                case 2:
                    ret = "矩形区域";
                    break;
                case 3:
                    ret = "多边形区域";
                    break;
                case 4:
                    ret = "路段";
                    break;
            }
            return ret;
        }

        /// <summary>
        /// 获取车辆状态
        /// </summary>
        /// <param name="Speed"></param>
        /// <param name="Acc"></param>
        /// <returns></returns>
        private static string GetCarStatus(int Speed, int Acc)
        {
            if (Speed > 0)
                return "行驶";
            else
            {
                if (Acc == 1)
                    return "停车";
                else
                    return "熄火";
            }
        }


        #region 获取路段行驶时间结果
        private string GetRoadResult(int nType)
        {
            if (nType == 0)
                return "过短";
            else
                return "过长";
        }
        #endregion

        #region 获取定位状态
        private string GetGpsStatus(int Flag)
        {
            if (Flag == 1)
                return "定位正常";
            else
                return "定位无效";
        }
        #endregion

        #region 获取电源状态
        private string GetPowerStatus(int Qy, int Dd)
        {
            if (Qy == 1 || Dd == 1)
                return "主电源欠压或断电";
            else
                return "电源正常";
        }
        #endregion



        /// <summary>
        /// poi纠偏
        /// </summary>
        public static void UsePoiGetNew(Gps gps)
        {
            if (gps.PosX >10)
            {
                return;
            }
            gps.PosX = gps.Longitude;
            gps.PosY = gps.Latitude;
            gps.PlaceInfo = "湖北省武汉市";
            try
            {
                //    string skey = GenKey(gps.Longitude, gps.Latitude);
                //    OFFSET_ONE off = redisGps.HashGet<OFFSET_ONE>("OFFSET", skey);
                //    if (off == null)
                //    {
                //        off = redisGps.HashGet<OFFSET_ONE>("OFFSET:" + skey.Split('|')[0], skey);
                //    }
                //    if (off != null)
                //    {
                //        gps.PosX = double.Parse((gps.Longitude + off.offsetlon).ToString("0.000000"));
                //        gps.PosY = double.Parse((gps.Latitude + off.offsetlat).ToString("0.000000"));
                double[] lngLat = ProjectionConvertUtil.wgs84togcj02(gps.Longitude, gps.Latitude);
                gps.PosX = double.Parse(lngLat[0].ToString("0.000000"));
                gps.PosY = double.Parse(lngLat[1].ToString("0.000000"));
                gps.PlaceInfo = GetPoi(gps.Longitude, gps.Latitude);
                //}
            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("UsePoiGetNew", ex.ToString());
            }


        }
        public static double AdjustX1ByPoiAllIdx(double x1)
        {
            double dis = 0;
            double mindis = double.MaxValue;
            double newx1 = x1;
            List<POI_ALL_INDEX> _hash_poi_all_idx = redisGps.StringGet<List<POI_ALL_INDEX>>("POIALLPATH:" + (int)x1);
            foreach (var item in _hash_poi_all_idx)
            {
                dis = Math.Abs(item.x1 - x1);
                if (dis < mindis)
                {
                    mindis = dis;
                    newx1 = item.x1;
                }
            }
            _hash_poi_all_idx.Clear();
            _hash_poi_all_idx = null;

            return newx1;
        }
        public static string GetPoi(double lon, double lat)
        {
            string strlast = "";
            string strlast1 = "";
            double x = double.Parse(lon.ToString("0.00"));
            double db = x;
            double db1 = x;


            bool bFound = redisGps.KeyExists("POIALL:" + db.ToString());

            if (!bFound)
            {
                db = AdjustX1ByPoiAllIdx(x);
            }

            var geoRadiusResults = redisGps.GeoRadius("POIALL:" + db.ToString(), lon, lat, 10000.0);

            if (geoRadiusResults.Length > 0)
            {
                GeoRadiusResult min = geoRadiusResults[0];
                string[] vs = min.Member.ToString().Split('_');
                if (vs.Length >= 2)
                {
                    strlast += vs[0].Trim();
                    strlast += ";";


                    strlast1 += vs[1].Trim();
                    strlast1 += "约";
                    strlast1 += (int)min.Distance;
                    strlast1 += "米";
                }
                geoRadiusResults = null;

            }

            bFound = redisGps.KeyExists("POIROAD:" + db1.ToString());
            if (!bFound)
            {
                db1 = AdjustX1ByPoiRoadAllIdx(x);
            }
            var geoRadiusResults1 = redisGps.GeoRadius("POIROAD:" + db1.ToString(), lon, lat, 1000000.0);

            if (geoRadiusResults1.Length > 0)
            {
                GeoRadiusResult min = geoRadiusResults1[0];

                strlast += min.Member.ToString().Trim();
                strlast += ",距离";
                geoRadiusResults1 = null;
            }


            return strlast + strlast1;
        }
        public static double AdjustX1ByPoiRoadAllIdx(double x1)
        {
            double dis = 0;
            double mindis = double.MaxValue;
            double newx1 = x1;
            List<POI_ROAD_ALL_INDEX> _hash_poi_road_all_idx = redisGps.StringGet<List<POI_ROAD_ALL_INDEX>>("POIROADPATH:" + (int)x1);
            foreach (var item in _hash_poi_road_all_idx)
            {
                dis = Math.Abs(item.x1 - x1);
                if (dis < mindis)
                {
                    mindis = dis;
                    newx1 = item.x1;
                }
            }
            _hash_poi_road_all_idx.Clear();
            _hash_poi_road_all_idx = null;

            return newx1;
        }

        private static string GenKey(double lon, double lat)
        {
            var strlon = lon.ToString("0.0000");
            var strlat = lat.ToString("0.0000");

            strlon = strlon.Substring(0, strlon.IndexOf(".") + 3);
            strlat = strlat.Substring(0, strlat.IndexOf(".") + 3);

            return strlon + "|" + strlat;
        }

        public static string ltGpsToSql(List<Gps> ltall)
        {
            string sql = "";
            string allSql = "insert into dev_gps_history(device_id,lng,lat,data_time,speed,direction,mileage,car_location,create_date)values";
            lock (sdObj)
            {
                sdDataCount += ltall.Count();
            }
            foreach (Gps gps in ltall)
            {
                //string sqlStr = "select device_id from  res_device  where device_phone_num = '" + gps.PhoneNum+ "';";
                //object device_id = DBHelp.DBHelp.executeSql(sqlStr);
                //if (device_id != null)
                //{
                sql += "(" + gps.deviceId + ", '" + gps.PosX + "', '" + gps.PosY + "', '" + gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss") + "', " + gps.Speed + ", " + gps.Direction + ", " + gps.Attach.Mileage + ", '" + gps.RegionInfo + gps.PlaceInfo + "',now()),";
                //sql += "(" + device_id + ", '" + gps.Longitude + "', '" + gps.Latitude + "', '" + gps.GpsTime.ToString("yyyy-MM-dd HH:mm:ss") + "', " + gps.Speed + ", " + gps.Direction + ", " + gps.Attach.Mileage + ", '" + gps.RegionInfo + gps.PlaceInfo + "',now()),";
                //}
            }
            allSql += sql;



            return allSql.Substring(0, allSql.Length - 1) + ";";
        }
   

        #region 获取最新的位置信息
        public static List<Gps> GetGpsInfo(string phones)
        {
            string[] para = phones.Split(',');
            List<Gps> LT = new List<Gps>();
            for (int i = 0; i < para.Length; i++)
            {
                if (GPSTable.ContainsKey(para[i]))
                {
                    LT.Add(GPSTable[para[i]]);
                }
            }
            return LT;
            // return new JavaScriptSerializer().Serialize(LT);
        }
        #endregion

        #region 获取间隔时间
        private static int GetMinutes(DateTime BeginTime, DateTime EndTime)
        {
            TimeSpan span = EndTime - BeginTime;
            return (int)span.TotalMinutes;
        }
        #endregion

        #region 获取车辆的运行状态
        public static string GetRunStatus(string id)
        {
            if (GPSTable.ContainsKey(id))
            {
                Gps gps = GPSTable[id];
                if (GetMinutes(gps.GpsTime, DateTime.Now) >= 30)
                    gps.RunStatus = "离线";
                return gps.RunStatus;
            }
            else
                return "";
        }
        #endregion

        #endregion

        static public void CheckOutTimePhoto(Object o)
        {

            try
            {
                List<ImageData> lt = new List<ImageData>();
                lock (MultiMediaDic)
                {
                    if (MultiMediaDic.Count > 0)
                    {
                        foreach (ImageData mudata in MultiMediaDic.Values)
                        {
                            DateTime star = mudata.ActiveTime;
                            //if (GPSTable.ContainsKey(mudata.phoneNumber))
                            //{
                            //    star = GPSTable[mudata.phoneNumber].HeartTime;
                            //}
                            TimeSpan span = DateTime.Now - star;
                            //string keyStr = mudata.phoneNumber + mudata.seqId.ToString();
                            if (span.TotalSeconds > 150 /*&& !hasSend8001.ContainsKey(keyStr)*/)
                            {
                                //List<int> packID = new List<int>();
                                //for (int i = 1; i < mudata.AllPackageNum + 1; i++)
                                //{
                                //    if (!mudata.PackList.ContainsKey(i))
                                //    {
                                //        packID.Add(i);
                                //    }
                                //}
                                //if (packID.Count != 0)
                                //{
                                //    int seqId = mudata.seqId;
                                //    byte[] body11 = BuildMsg.RequestOtherPackage(mudata.phoneNumber, seqId, packID.Count, packID);
                                //    SendTcpToPhone(body11, mudata.phoneNumber);
                                //    hasSend8001.Add(keyStr, body11);
                                //}
                                lt.Add(mudata);
                            }
                        }
                    }
                }
                foreach (ImageData mult in lt)
                {
                    //TimeSpan span = DateTime.Now - mult.ActiveTime;
                    ////string keyStr = mult.phoneNumber + mult.seqId.ToString();
                    //if (span.TotalSeconds > 180)
                    //{
                    if (!String.IsNullOrEmpty(mult.FilePath) && !String.IsNullOrEmpty(mult.SaveSql))
                    {
                        //SavePictureTofile(mult);
                        LogHelp.WriteeLog("", "强制存储照片成功：设备编号：" + mult.TerminalNumber + "，照片编号：" + mult.PhotoNum + "，照片SQL：" + mult.SaveSql);
                    }
                    else
                    {
                        lock (MultiMediaDic)
                        {
                            if (MultiMediaDic.Keys.Contains(mult.key))
                            {
                                MultiMediaDic.Remove(mult.key);
                            }
                        }
                        LogHelp.WriteeLog("", "强制存储照片失败：设备编号：" + mult.TerminalNumber + "，照片编号：" + mult.PhotoNum);
                    }
                }
                lt.Clear();

                string strSql = "update dev_gps_realtime set online_status=2 where  DATE_ADD(NOW(), INTERVAL -5 MINUTE) >update_time;";
                DBHelp.DBHelp.ExecSql(strSql);




            }
            catch (Exception ex)
            {
                LogHelp.WriteeLog("", "强制存储照片失败：" + ex.ToString());
            }

        }


    }
    public class ClientInfo
    {
        public IntPtr ConnId { get; set; }
        public string IpAddress { get; set; }
        public ushort Port { get; set; }
    }
}
